类方法和类变量
类变量static
- 类变量又名静态变量,是该类的所有对象共享的变量。任何一个该类的对象去访问它时,取到的都是相同的值;同样任何一个该类的对象去修改它时,修改的也是同一个变量。
public static int count = 0;
访问修饰符 static 数据类型 变量名
-
最大特点是会被child所有的对象实例共享。
-
必须遵守相关的访问权限。(public private protected)
-
类变量可以用类名访问:Child.count(Child类中的静态变量count)
-
不管static存储在哪里,共识:
- static所有同一个类的对象共享的
- 在什么时候生成的?在类加载的时候就已经生成了。
-
如何访问类变量?
-
类名.类变量名(推荐)。不用创建对象也能访问,因为类变量是随着类的加载而创建的。
-
对象名.类变量名
-
-
什么时候需要使用类变量?
-
某个类的所有对象都共享一个变量时(定义学生类,调剂所有学生共交多少钱)
-
与实例变量(普通属性)的区别:类变量是该类所有对象共享的,实例变量是每个对象共享的
-
-
类变量的生命周期是随着类加载而开始,随着类消亡而消失。
类方法static
- 也叫静态方法
访问修饰符 static 数据返回类型 方法名(){}
-
如何调用类方法?
-
类名.类方法名(推荐)
-
对象名.类方法名
-
-
当方法使用static修饰后,就是个静态方法,就能访问静态变量。
-
不用创建实例也可以调用某种方法时使用:Math.sqrt(),可以写自己的工具包
-
类方法中无this的参数,普通方法隐含this参数
-
类方法中不许使用和对象有关的关键字(调用直接使用变量名就行),比如this和super,普通方法可以
-
类方法只能访问静态变量或者静态方法;普通方法既可以访问非静态成员也能访问静态成员
main方法的语法
public static void main(String[] args) {}
-
谁在调用main方法?Java虚拟机在调用
-
Java虚拟机需要调用main方法,所以访问权限是public
-
Java虚拟机执行main方法时不必创建对象(有static),所以必须为static
-
该方法接受String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数
-
静态方法main不能访问本类的非静态成员,也不能调用本类的非静态方法,如果要使用,需要创建实例使用
代码块
又称为初始化块,属于类中成员,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。
但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。
[修饰符]{
代码
};
注意:
- 修饰符可选
- 使用static叫做静态代码块,无static为非静态代码块
- 逻辑语句中可以为任意逻辑语句
- ;可省略
好处:
- 相当于另一种形式的构造器(对构造器的补充机制),可做初始化操作
- 如果多个构造器中有重复语句,可以抽取到代码块中,提高代码的复用性(当不管调用哪个构造器创建对象都需要先调用代码块的内容)
- 代码块的调用优先于构造器
注意事项:
- static代码块叫做静态代码块,作用是对类进行初始化,随着类的加载而执行,且只执行一次;普通代码块每创建一个对象就执行一次(看作是构造器的一个补充,只有构造器被调用了才会调用普通代码块)
- 类什么时候被加载?
- 创建对象实例时(new)
- 创建子类对象实例时,父类也会被加载;而且父类先被加载再加载子类
- 使用类的静态成员时(静态属性、静态方法)
- 只是使用类的静态成员时,普通代码块不会被执行
- 代码块的调用顺序:
- 静态:多个静态代码块和静态变量初始化优先级相同,则若存在多个则按照定义的顺序调用
- 普通:多个普通代码块和普通变量初始化优先级相同,则若存在多个则按照定义的顺序调用
- 调用构造方法
- 构造器的最前面其实隐含了super() (继承父类时自动调用父类的无参构造器)。,静态代码块是优于构造器和普通代码块执行的。涉及父类时,首先调用父类的普通代码块,再父类的构造器,再本类的代码块,再本类的构造器。调用普通代码块
- 创建一个子类时,静态代码块、静态变量初始化、普通代码块、普通变量初始化调用顺序:
- 父类的静态代码块、静态变量
- 子类的静态代码块、静态变量
- 父类普通代码块、普通变量
- 父类构造器
- 子类普通代码块、普通变量
- 子类构造器
原因如下:创建对象时:
- 先进行类的加载
- 先加载父类,再加载子类
- 所以先执行父类的静态代码块、静态变量,再执行子类的静态代码块、静态变量
- 再创建对象
- 先走子类的构造器,隐含了一个super(父类的无参构造器)和普通代码块,所以先走父类,先执行父类普通代码块、普通变量,再执行父类构造器
- 父类执行完成后走子类普通代码块、普通变量,最后执行子类构造器
final
- 修饰类、属性、方法、局部变量
- 可能使用到final:
- 不希望类被继承时
- 不希望父类的某个方法被子类覆盖/重写(override),可以用final修饰
- 不希望类的某个属性值被修改,可以用final修饰
- 不希望某个局部变量被修改,可以用final修饰
注意事项:
-
final修饰的属性又叫常量,一般大写命名
-
final修饰的属性在定义时,必须赋初值,并且以后不能在修改。可在如下位置赋值:
- 定义时
- 构造器中
- 代码块中
-
final修饰的属性是静态时,初始化位置只能为:
- 定义时
- 静态代码块中
不能在构造器中赋值!
-
final类不能继承,但可以实例化对象
-
类不是final类但含有final方法,则该方法不能重写,但是能被继承
-
类已经是final了就没必要把方法设置为final了,因为类不能被继承了,怎么能重写呢?
-
final不能修饰构造器
-
final往往和static往往搭配使用,因为使用时不会导致类的加载,可以直接使用这个值(即不会调用静态代码块,静态代码块是在类加载时使用)
-
包装类、 string也是final类
抽象类
父类不知道方法具体如何实现时,就考虑讲方法设计为抽象方法。抽象方法就是没有实现的方法(即没有方法体)。当一个类中存在抽象方法时,需要将该类声明为abstract类。一般来说,抽象类会被继承,由子类来重写该方法。
- 抽象类不能被实例化
- 抽象类不一定包含抽象方法,还可以由实现的方法
- 一旦类中存在抽象方法时,必须将该类声明为abstract类
- 只能修饰类和方法,不能修饰属性
- 抽象类本质还是类,所以可以拥有类的任意成员
- 抽象方法不能有主体,即不能实现
- 如果一个类继承了抽线类,必须实现抽象类的所有方法,除非他自己也声明为抽象类
- 抽象类不能使用private、final、static修饰,因为这些关键词都是和重写相关的
接口
给出一些没有实现的方法封装在一起,到某个类需要使用的时候根据具体情况写出来。
alt+enter可以快捷实现所有方法
interface 接口名{
}
class 类名 implements 接口{
必须实现的接口从抽象方法
}
接口中,抽象方法可以省略abstract
注意事项:
- 接口不能实例化
- 所有方法都是public
- 一个普通类实现接口就必须实现接口里面所有方法
- 抽象类实现接口,可以不用实现接口的方法
- 一个类可以实现多个接口
- 接口中的属性只能是final,并且是public static final(默认)。
- 接口的属性访问形式:接口名。属性名
- 接口不能继承其他类,但是可以继承多个别的接口
- 接口的修饰符只能是public和默认,和类的修饰符是相同的
接口vs继承类
子类继承了父类就自动拥有了父类的功能
子类需要扩展功能可以通过实现接口的方式扩展
实现接口是对java单继承机制的补充
接口的多态
computer的work方法的参数是接口,那么可以通过接口名.方法来调用方法。在类中new了computer对象调用work时,computer.work()里面的参数可以是实现了接口的任意对象,这就体现了接口的多态。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V0t8fGP1-1679030711972)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230228222959673.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gvOxQEUq-1679030711973)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230228223045791.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SmLRpEpJ-1679030711973)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230228223301570.png)]
继承的多态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LYy1AdQR-1679030711974)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230228223343962.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-arnrCmoh-1679030711974)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230228223351028.png)]
多态数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8tZP01M-1679030711974)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230228223914407.png)]
内部类
一个类的内部又完整的嵌套了另一个类的结构 ,被嵌套的类被称为内部类。是类的五大成员(属性、方法、构造器、代码块、内部类)
最大特点:可以直接访问私有属性
分类:
-
定义在外部类局部位置上的:(比如在方法中)
-
局部内部类
-
匿名内部类
-
-
定义子啊外部类的成员位置上:
- 成员内部类(没用static修饰)
- 静态内部类(使用static修饰)
局部内部类
定义在外部类局部位置上的:(比如在方法中)。本质上仍然是一个类
- 可以访问外部类的所有成员,包括私有属性私有方法
- 不能添加访问修饰符,因为其地位就是局部变量,但是能用final修饰
- 作用域:在定义他的方法或者代码块中(相当于局部变量)
- 可以直接访问外部类的成员
- 外部类在方法中可以创建内部类的对象,然后调用方法即可。
- 外部其他类不能访问局部内部类
- 外部类和局部类成员重名时,遵循就近原则。如果想访问外部类成员,可以使用外部类名.this.成员(不是静态的,不能外部类名.成员),外部类名.this本质是外部类的对象
匿名内部类
定义在外部类局部位置上的:(比如在方法中)。并且没有类名!同时还是一个对象。
new 类或接口(参数列表){
类体
}
需求是类只使用一次,传统方法是写一个类然后实现接口并创建对象,较为繁琐。可以使用匿名内部类来简化开发。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1OwczAp3-1679030711974)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230301110647601.png)]
tiger编译类型IA,运行类型为该匿名内部类。
底层中其实是:class XXX implements IA{
public void cry(){}
},XXX是系统自动分配一个类名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9VLnOFAw-1679030711975)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230301111446611.png)]
- 调用匿名内部类的方法(两种):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qBy8O0Sp-1679030711975)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230301112106753.png)]
编译类型person,运行类型是匿名内部类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWjT6B99-1679030711975)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230301112238848.png)]
匿名内部类本身也是一个对象,可以直接调用
匿名内部类当作实参传递时最简洁有效。
成员内部类
定义位置是在外部类的成员位置上。
可以访问外部类的所有成员,包括私有属性私有方法。
任意添加访问修饰符,因为地位是一个成员。
作用域:在整个外部类中(相当于局部变量)
调用方式:作为一个外部类的成员,所以是外部类.内部类[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4fVauktm-1679030711975)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230301160642091.png)]
如果内部类成员和外部类成员重名,遵守就近原则;想访问外部类属性,可以使用外部类名.this.属性
静态内部类
定义位置是在外部类的成员位置上。
用static修饰
可以访问外部类的所有成员,包括私有属性私有方法。
任意添加访问修饰符,因为地位是一个成员。
枚举
定义枚举实现:
- 构造器私有化,目的防止直接new
- 去掉set方法,防止属性被修改
- 在season内部创建固定的一组对象。为什么要static,因为希望他可以直接访问(类变量)
public final static Season spring = new Season("spring", "warm");
注意事项:
- 不需要set方法,因为枚举对象通常为只读
- 对枚举对象使用final+static共同修饰,实现底层优化。
- 枚举对象名通常全部大写
- 枚举对象根据需要可以拥有多个属性
使用enum实现枚举类
- enum替代关键词class
- 直接使用SPRING(“spring”, “warm”):常量名(实参列表)
- 如果有多个,使用逗号间隔,最后一个带分号
SPRING("spring", "warm"),WINTER("winter","cold")
- enum实现枚举,需要讲定义常量对象写在属性前面
- 使用enum实现枚举类是不能再继承其他类了,java单继承机制,默认继承Enum类,但是可以实现接口
注意事项:
- enum开发枚举类时,默认继承Enum类,enum的枚举类是final类型
- 传统的public final static Season spring = new Season(“spring”, “warm”)简化为SPRING(“spring”, “warm”)调用的是两个参数的构造器
- 无参构造器创建对象,则可以省略小括号和实参列表
- 枚举对象必须放在枚举类的行首
enum常用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GEjZ01iP-1679030711976)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230302152305483.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zf6G9RQ4-1679030711976)(C:\Users\wsco24\AppData\Roaming\Typora\typora-user-images\image-20230302152819796.png)]
注解Annotation
元数据,用于修饰解释包、类、方法、属性、构造器、局部变量等数据信息。