0x00
本篇大纲,计划是分成几天来学,这几天要期末复习了
JAVAd的核心思想就是OOP(面向对象)
(看到接口我很兴奋
0x01 初始面向对象
属性+方法就是一个类
先有类再有对象,类是对象的模板
0x02 回顾方法
方法的调用
调用非静态方法
调用了student类中的非静态方法
静态方法:
形式参数和实际参数
值传递
引用传递
0x03 类与对象的关系
创建与初始化对象
先有个主类,在这个Application主类中有唯一的main方法
然后还有一个学生类
构造器
构造器也叫构造方法
构造器的几个特点:
0x04 创建对象和内存分析
第一步:加载Application这个类,里面有个main方法和一些常量
第二步:new的时候加载宠物类(生成这个模板),加载里面的属性和方法
第三步:生成一个实例dog,引用变量名dog放到了栈里,在堆里放了变量名dog引用的实例
这个时候name还是null
第四步:原来在第一步里加载的常量比如旺财,(值传递)传给了堆里的dog,这个时候dog里的属性才有值
引用变量名就是指向堆中的实例
静态方法区中关键字static定义的静态方法,会和类一起加载
这个图一定要理解!
0x05 简单小结类和对象
封装,继承,多态
0x06 封装
高内聚:类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅暴露少量方法给外部使用
属性私有:get/set
package OOP.OOP.Demo04;
public class Student {
//封装多对于属性:封装的核心在于私有
//属性私有
private String name;
private int age;
private char sex;
//提供一些可以操作这些私有属性的方法
//提供一些public的get,set方法
//get 获得这个数据
public String getName(){
return this.name;//可以获取到这个私有属性name
}
//set 给这个数据设置属性
public void setName(String name){
this.name = name;
}
//alt + insert 可以自动生成get,set方法
//通过内部的封装给set设置安全性验证的判断
public void setAge(int age) {
if(age>120||age<0){
this.age = 3;
}else{
this.age = age;
}
}
public int getAge() {
return age;
}
/*
封装的意义:
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.提高程序的可维护性
* */
}
补充:println方法里面写了很多重载方法
0x07 什么是继承
要想办法对类再进行抽象,所以出现了继承,对类再次进行细分抽象
继承就是拓展,是子类对父类的拓展
学生:派生类,字类
一个爸爸能有多个儿子,但是一个儿子只能有一个爸爸:单继承
Person.java
package OOP.OOP.Demo05;
//Java中,所有的类都默认继承object类
//父类 人
public class Person {
public void say(){
System.out.println("收了一句话");
}
public int money = 1000000000;
//ctrl+h 打开继承树
}
Student.java
package OOP.OOP.Demo05;
//学生 is 人
public class Student extends Person{
}
Application.java
package OOP.OOP;
import OOP.OOP.Demo05.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
//子类可以继承父类的所有方法和属性,前提是public修饰符
s1.say();
System.out.println(s1.money);
}
}
super
super可以和this对比,一个代表父,一个代表当前的
方法也可以用super调用
但是如果父类的方法用private构造会不能访问
super(); 能调用父类的构造器,必须要在子类构造器的第一行
0x08 方法的重写
重写都是方法的重写,和属性无关
静态方法(static)的调用只和左边,定义的数据类型有关(和多态有关系)
重写只和非静态方法有关
可以alt+insert来直接构建重写方法
下面用非静态方法演示重写
0x09 什么是多态
多态,可以实现程序的动态编译,可以让可扩展性更强
Application方法
package OOP.OOP;
import OOP.OOP.Demo06.Person;
import OOP.OOP.Demo06.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是决定的
//new Student();
//new Person();
//可以指向的引用类型就不确定了:父类的引用指向子类
Student s1 = new Student();
//Student 能调用的方法都是自己的或者继承父类的
Person s2 = new Student();
//Person 父亲类,可以指向字类,但是不能调用子类独有的方法
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
//强转类型从
((Student) s2).run();
s1.run();
}
}
static,final,private方法无法实现重写,更别谈多态了
引用一般指父类,或者有关系的类
0x010 instanceof 和类型转换
instanceof关键字,判断是否属于
如果没有关系,就会报错
类型的转换
Application.java
package OOP.OOP;
import OOP.OOP.Demo06.Person;
import OOP.OOP.Demo06.Student;
import OOP.OOP.Demo06.Teacher;
public class Application {
public static void main(String[] args) {
//类型之间的转换:父 子
//高 转 低
Person obj = new Student();
//student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
Student student = (Student) obj;
//go方法在student类型里
//将这个类转为student类型,就能使用Student里的方法了
student.go();
}
}
但是如果子类要转换为父类,向上转,就可能会丢失自己本来的一些方法
0x011 static关键字详解
静态属性和方法
只能Stunent.age,调用静态的变量
非静态方法可以调用静态方法
静态方法只能调用静态方法,因为static在类加载的时候一起载了,这个时候没有加static的东西还没有被实例化加入内存
这些都和类的加载顺序有关
静态代码块
package OOP.OOP.Demo07;
public class Person {
{
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person p1 = new Person();
System.out.println("++++++++++++++++++++++++");
Person p2 = new Person();
}
}
输出如图:
所以静态代码块只加载一次
静态导入包
修饰符final
被final修饰的不能被继承
0x012 抽象类
关键字abstract
Action.java
package OOP.OOP.Demo08;
//抽象类:类 extends:单继承 (但是接口可以实现多继承)类比于插座
public abstract class Action {
//约束 有人帮我们实现
//abstract 抽象方法,只有方法的名字,没有方法的实现
public abstract void doSomething();
//抽象类的特点:
//1. 不能new出来,只能靠子类去实现它; 对子类实现约束
//2. 抽象类中可以写普通方法
//3. 抽象方法必须在抽象类中
//抽象的抽象:就是约束
}
A.java
package OOP.OOP.Demo08;
//抽象类的所有方法,继承了他的子类必须要实现他的方法,除非他的子类也是抽象类。。。
public class A extends Action{
//继承抽象类,必须要重写抽象类的方法
@Override
public void doSomething(){
}
}
-
有抽象方法的类一定是抽象类
-
是抽象的类不一定要有抽象方法
-
无法通过new实例,通过继承
-
子类必须实现所有的父类抽象方法,否则也要注明abstract
思考题
抽象类存在构造器吗
答:存在的,给子类用的,即使你没有提供任何构造函数,编译器将为抽象类添加默认的无参数的构造函数,没有的话你的子类将无法编译,因为在任何构造函数中的第一条语句隐式调用super()。
抽象类存在的意义:
答:抽象出来必须要实现的东西,提高开发效率,进行约束
0x013 接口
interface关键字
TimeService接口
package OOP.OOP.Demo09;
public interface TimeService {
void timer();
}
UserService接口
package OOP.OOP.Demo09;
//锻炼抽象的思维
public interface UserService {
//接口中的所有定义方法都是抽象的,都是public abstract的
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
//接口中定义的属性都是常量public static final
int AGE = 99;
}
UserServiceImpl
调用接口的类
package OOP.OOP.Demo09;
//接口可以多继承
//接口的实现类,用Impl来命名结尾,来实现UserService接口
//实现了接口的类,就需要重写接口中的方法
public class UserServiceImpl implements UserService,TimeService{
//利用接口实现多继承
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
接口的一些作用:
1.约束
2.定义一些方法,让不同的人实现
3.public abstract
4.public static final
5.接口不能被实例化,接口中没有构造方法
6.implements可以实现多个接口
7.必须要重写接口中的方法
0x014 内部类
内部类就是在一个类的内部再定义一个类
正常内部类
package OOP.OOP.Demo10;
public class Outer {
private int id;
public void out(){
System.out.println("外部类的方法");
}
public class Inner{
public void in(){
System.out.println("内部类的方法");
}
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
++++++++++++++++++++++++++++++++++++++++++++++++
package OOP.OOP;
import OOP.OOP.Demo10.Outer;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
静态内部类无法访问外类中的方法
局部内部类
package OOP.OOP.Demo10;
public class Outer {
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
//一个java类中可以有多个类,但是只能有一个public类
class A{
public static void main(String[] args) {
}
}
下面的看懂即可
package OOP.OOP.Demo10;
public class Test {
public static void main(String[] args) {
//没有名字初始类
new Apple().eat();
UserService userService = new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService {
void hello();
}