三大修饰符
abstract——抽象
引言:父类通常是子类共性提炼出的概念,同来总结和约束子类,所以不应该能够被实例化对象。建立在此基础上,父类中的某些行为方法的方法体也不应该存在,因为永远无法施行
抽象类
public abstract class 类名{}
abstract public class 类名{}
修饰符之间的书写顺序不做要求
使用规则:
1:无法实例化对象
2:通常情况下,父类应该成为抽象类
3:抽象父类中仍然存在构造!! 作用为方便子类构造的执行
4:抽象类中可以存在非抽象内容!!方便子类直接继承使用
5:抽象父类仍然可以参与多态
抽象方法
访问修饰符 abstract 返回值类型 方法名(形参列表)
使用规则
1:只能存在于抽象类
通常情况下,抽象父类中的行为方法都应该是抽象方法
2:子类必须对父类的抽象方法提供重写
非抽象子类无法存在从父类继承过来的抽象方法
可以将子类也声明为抽象类,就可以不重写父类抽象方法!!从程序上设计来看,不推荐这么做
3:抽象父类的抽象方法作用
在强制要求子类必须拥有该方法的基础上也必须提供方法重写
抽象类和抽象方法的关系
1:抽象类中可以存在非抽象方法
2:抽象方法必须存在于抽象类
抽象的好处
1:可以是父类单纯为子类服务
2:更符合程序设计及显示逻辑
static——静态
静态属性
访问修饰符 static 数据类型 属性名
使用规则:
1:不被某个对象独有,被该类的所有对象共享
2:静态内容独立存放在方法区的静态内容区中
JDK8.0之后,方法区被迁移至堆空间之中
3:可以通过类名.属性名的方式直接访问静态属性
4:如果静态属性进行了封装,无法通过类名.属性名直接访问属性
getter、setter方法不是静态的,则需要通过任意对象名.方法名访问
getter、setter方法是静态的,则可以需要通过类名.方法名访问
类加载
在第一次使用类内容时,通过CLASSPATH类路径找到对应的字节码文件,将字节码文件中的内容加载到虚拟机的过程,称之为类加载。通常情况下,类加载只会发生一次
类加载的时机:
1:第一次创建类的对象时
2:第一次访问静态内容时
3:通过class.forName("全限定名")的方式强制触发类加载
全限定名:类的完整路径,包名.类名
4:子类类加载也会触发类加载
5:只声明引用不会触发类加载
注意:静态内容出现在内存中的时间一定早于非静态内容
静态内容:类加载
非静态内容:创建对象时
静态方法——函数
使用规则:
1:可以使用类名.方法名(实参)的方法调用
静态内容,存放在方法区
2:无法访问非静态内容
访问静态方法时,非静态内容在内存中有可能还未存在
实例方法任何内容都可访问,当实例方法执行时静态内容必定已经存在
3:无法使用this和super关键字
this表示当前对象,super表示父类对象。静态方法执行时有可能对象并未创建
4:无法修饰局部变量
局部变量的作用范围限制其无法成为类变量(静态属性)
5:子类可以继承并重写父类静态方法
6:在多态的语法环境下,子类的重写意义不大
静态内容的执行关注的是引用类型
7:无法修饰构造
构造方法只能通过new关键字调用
修饰初始代码块-了解
初始代码块
是所有构造共性内容的提炼,在构造执行之前执行,通常用于给属性赋值
class 类名{
{
//初始代码块
}
}
使用规则
1:位置:类以内,方法以外,与属性方法平级
2:在创建对象时执行
3:执行次数:0-n次
静态初始代码块
class 类名{
static {
//静态初始代码块
}
}
使用规则:
1:类加载的时候执行
2:执行次数:0-1次
3:使用限制于静态方法一致
final——最终
修饰类————不可被继承
修饰方法————可以被继承,不可被重写
修饰属性————会变成常量属性,值不可改
常量属性没有默认值,为了保证空间的分配,常量属性创建时,必须赋值
时机1:声明的同时直接赋值
时机2:在构造中赋值
必须保证每个构造中都存在赋值语句
也可以将赋值语句直接写进初始代码块
修饰引用
对象内容可改,对象地址不可改
接口
引言(概念):
1:从功能上看:实现接口就意味着扩展了某些功能
2:从规则上看:是接口定义者和实现者都需要遵守的某种规则
3:从抽象上看,接口是特殊的抽象类
语法:
[public] interface 接口名{}
包:com.xxx.dao
使用规则
1:属性必须为公开静态常量(public static final)
由于修饰符固定,所以可以省略或者缺失,编译器会自动填充
2:方法必须为公开抽象方法
3:没有构造方法
4:无法实例化对象
实现类
[public] class 类名 implements 接口名{}
com.xxx.dao.impl
规则
实现类必须对接口中的所有抽象方法提供方法实现
可以将实现类声明为抽象类避免方法重写,但是不推荐
2:一个实现类可以实现多个接口,一个接口也可以拥有多个实现类(多实现)
[public] class 类名 implements 接口1,接口2{}
3:当实现类实现多个接口时,必须对所有接口的所有抽象方法提供方法实现
4:一个类可以同时继承父类和实现接口,必须先写继承再写实现
[public] class 类名 exends 父类类名 implements 接口名{}
5:仍然可以使用多态创建对象(推荐)
接口名 引用名=new 实现类名()
6:接口与实现类之间的多态应用规则与父子类之间无任何差异
只能调用引用类型中声明的内容
调用独有内容前需要类型强转
实现类名 引用名=(实现类名) 接口引用名;
仍然可以使用instanceof关键字判断类型兼容
引用名 instanceof 接口名|实现类名
接口与实现类之间仍然适用多态的三个使用场景
接口间的继承
一个接口可以继承多个接口(多继承)
interface 子接口名 extends 父接口名1,父接口名2{}
子接口可以继承拥有父接口中的所有内容
接口和抽象类的区别
抽象类 | 接口 | |
关键字 | abstract class | interface |
属性 | 不做具体要求 | 公开静态常量 |
方法 | 可以存在非抽象方法 | 公开抽象方法 |
构造 | 有 | 无 |
继承性 | 单继承 | 多继承 |
接口高级
高版本的接口
JDK8.0
公开的默认方法
public default 返回值类型方法名(参数列表){
//操作语句
}
public为访问修饰符,default为标识符,作用是与抽象方法做区分
当父类中的方法体内内容与接口中的出现冲突时,优先执行父类(类优先原则)
当多个接口中的方法体内容出现冲突时,实现类必须对冲突方法再次提供重写,然后使用自身内容
2:公开的静态方法
public static 返回值类型 方法名(参数列表){
//操作语句
}
可以通过接口名.方法名(实参)的方式直接调用执行
JDK9.0
私有方法:
private 返回值类型 方法名(参数列表){//操作语句}
接口回调
开闭原则:扩展开放,修改关闭
允许在现有代码的基础上扩展功能,但是前提不允许更改已有的代码
概念
将方法的形参声明为接口类型,在传入实参时,可以传入不同的实现类对象
本质就是多态的第二次使用场景的体现
比较器案例
1:建造比较器接口的实现类,并重写排序方法
public class 实现类 implements Comparatoe<被排序的类名>{
public int compare(被排序的类名 o1,被排序的类名 o2){//排序规则}
}
2:书写排序规则
从大到小
o1的值>o2的值,返回正数
o1的值<o2的值,返回负数
相等,返回0
从大到小:相反
3:调用java.util.Arrays.sort(被排序的数组名,Comparator接口的实现类对象)执行数组排序
内部类
概念:在类的内部再次定义类
作用:打破封装, 又不破坏封装
分类:成员内部类、静态内部类、局部内部类、匿名内部类
成员内部类
外部类内部,与外部类属性,方法平级
class 外部类类名{
calss 内部类类名{
}
}
使用规则:
1:无法定义静态内容,可以访问外部类静态内部
2:当外部类属性、内部类属性、内部类局部变量重名时
局部变量:直接访问
内部类属性:this.属性名
外部类属性:外部类类名.this属性名
3:对象创建需要借助外部类对象
外部类类名.内部类类名 对象名=外部类对象名.new 内部类类名();
静态内部类
位置与成员内部类一致
class 外部类类名{
static class 内部类类名{
}
}
1:使用规则:可以定义静态内容,无法访问外部类非静态内容
2:内部类属性和外部类属性重名时,通过各自类名访问即可
3:对象创建需要借助外部类类名
外部类类名.内类类名 对象名 = new 外部类类名.内部类类名();
4:可以直接通过外部类类名.内部类类名.静态内容的方式直接访问内部类静态内容
局部内部类
位置:外部类方法内部,与外部类局部变量平级
class 外部类类名{
访问修饰符 返回值类型 方法名(参数列表){
class 内部类类名{ }
}
}
使用规则:
无法通过访问修饰符修饰
作用范围与局部变量一致
无法定义静态内容,但是可以访问外部类静态内容
可以访问外部类的局部变量,前提是其为常量
JDK7.0之前,必须是通过final修饰的显式常量
JDK7.0之后,未二次赋值的事实常量即可
只能在所属方法内部创建对象
匿名内部类
实际开发中,部分类知乎i使用一次(创建一次对象),之后不会二次使用,匿名内部类可以节省这种类的开发成本
特点:
将类的声明、方法的实现、对象的创建三合一
语法:
父类类名|接口名 引用名=new 父类类名|接口名(){}
使用规则:
1:对象创建必须使用多态
2:匿名对象一定继承自父类或者实现自接口
由引用类型决定
3:与独立声明class类的区别
1:独立声明class的类拥有具体类名,但是匿名类内部没有具体命名
2:独立声明class的类可以反复多次创建对象,但是匿名内部类只能在语法结构执行时创建一次对象
4:内部存在构造(默认的无参构造)且构造无法显式定义
5:内部可以定义独有内容,但是外部无法访问,只能在类的内部使用
lambda表达式
JDK8.0
作用:
简化部分匿名内部类的书写,可以生成一个接口实现类对象
语法:
( 形参列表)->{操作语句}
结合引用;
接口名 引用名 = (形参列表)->{操作语句};
接口的分类
1:标记式接口:无任何内容
2:函数式接口:内保护只有一个需要重写的方法
3:常量式接口:内部只声明了属性
4:普通接口:内部声明了多个需要重写的方法
使用规则
1:只能作用与函数式接口
2:无法定义独有内容,只关注唯一方法的实现
3:简化标准:
形参的数据类型可省!!省略就全省
参数只有一个的时候,小括号可以省略
操作语句只有一条的时候,大括号可以省略
操作语句只有一条并且return语句时,大括号和retturn都可省略!省略就全部省略
常用类:
object
1:是所有类的总父类,只要是类就一定直接或者间接继承自Object
2:内部存放着所有对象都需要拥有的方法
3:可以根据需求对其中的部分方法提供重写
常用方法
1:class类对象 getclass()用来获取当前引用的实际对象类型
2:int hashCode():获取当前对象的哈希码值
重写原因:该方法默认关注对象地址,但是实际开发过程中,我们某些情况下需要关注的是对象内容,内容相同则哈希码值相同,所以需要重写
重写规则:
1:整型:直接相加:long类型需要类型强转为int
2:浮点型:强转int后相加
3:引用类型:调用hashCode()方法相加
类库中的引用类型(String、包装类等):直接调用
自定义的引用类型:先重写该类额hashCode再调用
3:boolean equals(Object o):判断当前对象与参数对象是否相同
重写原因:该方法默认比较地址,但是实际开发中,在某些需求下需要比较对象内容,所以需要重写
重写规则:
public boolean equals(Object o){//Object o=new Student();
//自反性:自己与自己比,一定相同
if (this == o) {
return true;
}
//非空判断+类型比较:与null值比或者实际对象类型不一致,一定不同
if (o == null || this.getClass() != o.getClass()) {
return false;
}
//类型强转:把参数对象类型强转为当前类型,方便比较属性值
当前类名 引用名 = (当前类名) o;
//进行属性值比较
//用this对象和引用名的属性进行比较:
//基本类型==直接比较,引用类型调用equals方法进行比较
//类库中的引用类型:直接调用
//自定义的引用类型:重写对应类的equals,然后调用
return ...;
}
4:String toString():获取对象的详细内容
特点:在直接查看引用名时,可以默认调用
重写原因:该方法默认获取对象地址,但是实际开发中,我们有可能需要查看对象属性信息,所以需要重写
重写规则:
按照需求拼接字符串发挥即可
5:void finalize()用于被虚拟机调用进行垃圾对象回收
垃圾回收机制:当内存满到不足以支撑新对象的创建时,虚拟机会自动调用垃圾对象的finalize方法对其进行回收销毁,从而释放空间
垃圾对象的判断标准:没有任何引用指向的对象(零引用机制)
手动垃圾回收:借助垃圾回收器(GC),通过System.gc()实现手动垃圾回收
包装类:
作用:将八大基本类型,包装为引用类型,使其保留数值操作简单的基础之上可以处理null值
byte | short | int | long | float | double | chat | boolean |
Byte | Short | Integer | Long | Float | Double | Chatacter | Boolean |
包装类型和基本类型
基础类型转成包装类型
利用构造:
包装类名 引用名 = new 包装类名(基本类型)
利用valueOf方法:
包装类名 引用名 = 包装类名.valueof(基本类型);
包装类转换为基本类型
利用xxxvalue方法
基本类型 变量名=包装类对象.xxxValue();!!!注意:xxx表示对应基本类型名
拆箱封箱
JDK5.0之后,为了提高包装类型与基本类型之间转换的效率,提供了自动封箱和自动拆箱操作,使其可以直接相互赋值自动完成转换
封箱:基本类型转成包装类
拆箱:包装类转成基本类型
基本类型与String
基本类型转成String
1:拼接双引号:
String 引用名=基本类型+“”;
String 引用名=““+基本类型;
利用valueOf方法
String 引用名=String.valueOf(基本类型);
String 转成基本类型
利用patse方法
基本类型 变量名=对应包装类型.parseXxx(String类型);
String转包装类
与基础类型转包装类的两种方式一致
整数缓冲区
官方认定,-128至127是最常用的256个数字,为了避免包装类型数字重复使用带来的内存压力,在方法区中设立了整数缓冲区,缓冲区中存放该256个数字,当包装类型使用的数字在此范围内时,会直接引用缓冲区地址
==比较引用类型时,堆地址优先
String
是内存中的常量,值在内存中一旦创建,不可改
创建方式
1:直接双引号赋值
String 引用名=“值”;
’2:构造赋值
String 引用名 =new String("值");
串池
全称是:字符串常量池。
实际开发中,字符串是使用频率最高的数据类型,且复用度也很高,为了避免重复的字符串内容反复开辟空间造成的空间资源浪费,所以在方法区中设立了串池,目的为节省空间。
区别:
第一种创建方式:优先使用串池,先从串池中查找有无对应字符串内容,有,让引用直接指向对应串池地址,无,则先在串池中创建该字符串内容,然后再让引用指向
第二种创建方式:无论如何都会开辟对象空间地址。开辟完对象空间之后,进入串池查找内容是否存在,存在,则直接存放对应串池地址,不存在,则先在串池中创建该内容,然后再存放串池地址
可变长字符串:
值可改
StringBuffer:JDK1.0 线程安全,效率低
StringBuilder:JDK5.0 相较于StringBuffer来说,线程不安全 效率高
特点:必须通过构造创建,所有字符串内容操作必须借助方法完成
与String的区别
1:String是内存中的常量,值不可改,可变长字符串值可改
2:String 可以使用串池,对一个字符串内容反复使用的频率要远远高于更改的频率,所以可以使用串池的String要由于可变长字符串
String的常用方法
String引用名.方法名(实参);
-
char charAt(下标):获取指定下标位置的元素
-
boolean contains(字符串):判断当前字符串是否包含指定内容
-
boolean endsWith(字符串):判断字符串是否以指定内容结尾
-
boolean startsWith(字符串):判断字符串是否以指定内容开头
-
boolean equals(字符串):判断字符串内容是否相同,区分大小写
-
boolean equalsIgnoreCase(字符串):判断字符串内容是否相同,不区分大小写
-
String toUpperCase():转全大写
-
String toLowerCase():转全小写
-
int length():获取字符串长度
-
int indexOf(字符串):获取指定内容第一次出现的下标
-
int lastIndexOf(字符串):获取指定内容最后一次出现的下标
-
boolean isEmpty():判断字符串内容是否为空,不能判比null值
-
String replace(旧字符串,新字符串):将字符串指定旧内容替换为新内容,全部替换
-
String[] split(字符串分隔符):将字符串按照指定分隔符进行分割,不保留分隔符
-
String subString(起始下标):将字符串从起始下标截取至末尾
-
String subString(起始下标,结束下标):将字符串从起始下标截取至结束下标前一位
-
String trim():去除字符串前后空格
-
byte[] getBytes():以byte数组的形式返回字符串的内容
-
char[] toCharArray():以char数组的形式返回字符串的内容