面向对象
什么是面向对象?
面向对象顾名思义就是把现实中的事务都抽象成为程序设计中的“对象”,其基本思想是一切皆对象,是一种“自下而上”的设计语言,先设计组件,再完成拼装
类:用来描述一个对象的基本范式模板,创建对象的时候参照这个模板来进行创建,即构造器
引用数据类型可以相当于是自己定义的一种全新的数据类型,是一种自定义的数据类型,类似于一个对象;
成员
成员是属于对象的,而不是属于类的,所以每个对象虽然是依照类来创建,但可以有不同的成员属性
局部变量是在代码块中的变量,就是局部位置。其他的位置都是成员位置,成员变量随着对象的消亡而消亡;
this
this关键字指向的是当前对象中的成员变量,用来和局部变量做区分
所有的成员方法都会隐含一个this传参,指向的就是当前的对象,但由于就近原则,如果方法的形参列表中有一个同名的局部变量,就会默认使用局部变量,因此需要用this来指向成员变量
这里要注意:static方法是没有隐含一个this传参的,如果要访问成员变量就需要创建对象
构造方法
构造方法必须和类名相同,new对象会自动调用构造方法,并且构造方法无法通过普通方法的调用方式来调用
构造方法可以重载
其他方法也可以和类名相同,但必须带有返回值或者void
构造方法的赋值永远是最后执行的,你可以永远相信构造器
static
静态属性是属于类的而不是对象的,是全体对象所共享的,包括变量和方法
静态成员的加载是随着类加载进行的,且不依赖对象而存在
类加载只有一次,所以静态成员也只有一份,且被所有对象共享
这里注意与成员变量的区别:成员变量是每个对象独一份的
静态成员使用类名.的形式来访问,不建议通过对象名访问
静态变量存放在方法区中的静态区,被所有对象共享;
成员变量存放在堆内存中,每个对象独享自己的成员变量;
不存在静态的局部变量
匿名对象
没有引用指向,直接new出来的对象就是匿名对象
使用的场景:作为参数、返回值
使用一次之后就会被回收,无法再次访问到
代码块
局部代码块
基本用不着,就是用来限制局部变量的生命周期,优化内存
构造代码块
定义在类的成员位置,随着构造器的执行而执行,
显式赋值和构造代码块的执行顺序:谁写在上面就先执行谁
静态代码块
随着类加载的进行而执行,可以看作一个在类加载过程中会被自动调用的静态方法,不能在里面调用非静态的成员
和构造代码块一样,在对静态变量进行赋值的时候,谁写在上面就先执行谁
如果一个类的静态代码块没有被执行,就说明没有完全类加载
导包
这里要注意,在使用智能导入的时候会根据需要来智能导入需要的类
import + 包名.*; • 1
但有一个条件:如果不导入对应包下的类就会报错,才会导入
访问权限修饰符
public:任意类都可访问,不限制访问权限
protected:同包下的其他类和其他包的子类可访问
deafault:默认权限,只有同包下的其他类能访问,不关心是不是子类
private:只有同类中的其他成员可见
面向对象的三大特征
封装
将设计者和使用者区分开来,使用者只用关心怎么使用,不必关心怎么实现
继承
Java中,一个子类只能有一个(直接)父类,
父类对象的范围大
子类继承了父类的成员,如果在父类中修改成员变量和方法,会影响所有子类
Java中没有多继承,祖先类都是objec
不能继承的:私有成员不能继承,构造方法不能继承
静态成员可以继承
子类对象的初始化:
类加载是先父后子的,但成员变量都会有默认初始化具有默认值,这个过程不考虑先后的顺序。
子类对象在创建后,在自身的内存区中会有一部分用来存放父类的对象属性
除了默认初始化外的其他赋值方式都是先父后子的
隐式初始化:在子类的构造器中,如果没有this、super,会永远默认在第一行调用父类的无参构造,但无法完成父类成员变量的赋值,此时父类的成员变量只具有默认值
super关键字指向的是父类中的成员,受访问权限的限制,this关键字关键字指向的是自身对象,不受访问权限的限制
方法重写:子类中出现与父类同名的方法,会将父类的方法覆盖掉,但仍可以用super关键字来访问
要求:方法名相同,形参列表相同,必须是子类重写父类,不能抛出更多异常,访问权限只能更加宽松,返回值类型如果是引用数据类型,可以返回兼容的类型(子类)
不能重写的方法:私有、静态、构造方法
final
final修饰类表示无法继承
final修饰方法表示无法被重写,但可以被继承
final修饰变量:表示将该变量设置为常量
修饰基本数据类型表示值不可更改,修饰引用数据类型表示引用指向的地址值不可以更改,即该引用无法指向一个新的对象,但对象中的内容仍然是可以更改的
方法体中用final修饰局部变量表示该变量无法改变
方法的形参列表中用final修饰表示实参一旦传入,就无法修改了
成员常量:final 修饰的就是成员常量,无论使用什么方法,只能赋值一次并且不能更改,默认值不能作为常量,所以也必须要赋值,但每个对象都可以拥有属于自己的成员常量
全局常量:final修饰的静态变量,访问全局常量不会触发静态代码块
多态
多态发生的条件:父类引用指向子类对象,并有方法重写
成员变量的访问特征:编译时(访问范围)看左边,运行时(访问结果)看左边
成员方法的访问:编译(访问范围)看左边,运行时(调用结果)看右边
这里注意:不管是什么方法,都只会看右边的结果,包括静态
向上转型:子类引用转父类引用,不会出问题
向下转型:父类引用强转子类引用,可能出问题
要判断转向的那个子类引用和对应的那个对象是否是相同类型
引用名 instanceof 类名 • 1
抽象类
可以定义抽象方法,abstract,没有方法体,必须被子类重写,不能和final一起使用,但如果是抽象类继承抽象类,可以不用重写
抽象类可以有普通的成员方法和变量,也可以被继承
抽象类不能创建对象,但可以有构造器
除了多出一个抽象方法之外,别的都和普通类一样
任何不能被继承、重写的方法都不能定义为抽象
接口
访问权限只有public和默认
接口不受多继承限制,可以被多实现,抽象类继承接口可以不重写
如果一个类实现接口并继承别的类,要"先继承再实现"
接口的方法默认被public abstract修饰
接口的成员变量默认是全局常量,必须用显式赋值,接口中也没有静态代码块
接口中可以有默认方法default和静态方法static
接口和接口之间可以多继承,但接口和类不能相互继承
内部类
外围类:包含内部类的类
外部类:不相关的其他类
成员内部类
不能有静态成员,即无法使用static
访问特点:
内部类与外围类:访问不受权限的限制,包括私有
内部类访问外围类成员:
成员内部类的方法中隐含有自身对象和外围类的对象,所以可以直接访问外围类的成员,但如果出现同名的情况,遵循就近原则,如果要访问外围类的成员,自身的对象用this指向,外围类对象用外围类类名.this"指向
外围类访问内部类成员:
成员方法中:需要创建内部类对象,因为外围类自身的对象已经存在,直接new 内部类即可,如果有同名的情况,用对象名指向的就是内部类,否则就是外围类
静态方法中:需要先创建外围类对象,再在此基础上创建内部类对象
MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz(); • 1
外部类访问内部类成员:
首先要有外围类的访问权限,其次还要有内部类的访问权限
先创建外围类对象,再创建内部类对象,接收的时候要写明该内部类属于哪个外围类
EnclosedClazz.MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz();( • 1
创建完之后,用对象名访问
成员内部类访问外部类:
直接创建对象就能访问,受访问权限限制
静态内部类
静态内部类是一个独立的类,相当于嵌套在外围类中,和外围类没有强依赖关系
内部类和外围类之间不受访问权限的影响,但由于静态成员是不带有对象的,因此要访问谁,就创建谁的对象来访问
外部类访问静态内部类成员,之间创建静态内部类对象即可,但在使用引用接收的时候要表明该静态内部类属于哪个外围类
外围类类名.静态内部类类名 • 1
静态内部类访问外部类直接创建对象,受权限的限制
静态内部类的类加载和创建对象都和外围类没有直接的关系,不会互相触发
局部内部类
定义在一个方法或者作用域之中的类,没有访问权限修饰符,其他特点和成员内部类一致
局部内部类访问外围类成员:
1.在外围类的成员方法中定义的局部内部类:
访问特点与普通成员内部类一致
2.在静态方法中定义的局部内部类:
需要创建外围类对象才能访问外围类成员
外围类访问局部内部类成员:只能在装着局部内部类的方法中创建对象才能访问
外部类不能访问局部内部类成员,但局部内部类可以访问外部类成员
局部内部类的成员方法中不能修改方法的局部变量,是一个实际上的常量
lambda
匿名内部类
没有引用指向,相当于是一个类/接口的子类的类体,用来重写里面的方法
匿名内部类实质上就是创建一个子类对象,
匿名内部类语法中的小括号可以填入参数表示调用某个构造方法,但是注意只有类有构造器
使用场景:方法需要传入或者返回一个对象
lambda表达式
是特殊的匿名内部类
使用前提:只能实现功能接口,相当于该接口的子类
语法:()->{}
lambda表达式类型的推断:
1.直接用父类接口引用接收
2.告诉编译器类型:(父接口的名字)lambda表达式
3.借助方法的形参列表或者返回值
简化:
形参列表:
形参的数据类型可以简化,如果只有一个形参,括号可以省略,但如果没有形参就不能省略
方法体:如果只有一条语句,可以省略大括号,如果是返回值语句,return也能省略
方法引用:
功能接口 接口名 = 方法的归属者::方法名;
静态方法的归属者是类,成员方法是对象
什么样的方法能被引用:返回值类型一直,形参列表中的数量、类型、位置必须对应,名字无所谓
lambda表达式只能重写方法,不能定义成员