java冷知识:
在Java语言中,一个String字符串常量对应着一个String对象,并且是不可更改和继承的(因为String类被final关键字修饰)。Java语言这样设计,主要是为了使得字符串常量(注意是字符串常量,字符串变量不符合这里所讲的规则)可以共享,因为JVM将字符串常量放入公共的存储池中,不同的变量可以引用相同的字符串常量。
以上代码运行结果为:true。这就说明a和b引用的是同一String对象。
1.继承
继承关键字extends
作用:子类继承父类后,可以直接使用父类的公共属性和方法。
好处:提高代码的复用性。
创建子类对象时,会在堆内存中为分配一块内存,该内存由两部分组成,一部分是子类空间,另一块是父类空间,子类空间通过this来访问,父类空间通过super来访问。
特点:
- 子类可以继承父类的属性和行为,但是子类不能继承父类的构造器
- java是单继承模式:一个类只能继承一个直接父类
- java不支持多继承、但是支持多层继承
- java中所有的类都是object类的子类
子类可以继承父类私有成员,只是不能直接访问(需要通过反射来访问)
子类可以访问父类的静态成员,但是不算是继承,只算是共享访问
子类访问成员(变量、方法)满足:就近原则
- 先去子类局部范围找
- 然后去子类成员范围找
- 最后去父类范围找,如果父类范围没有,则报错
重写:
@Override 作用
1.重写校验注解,程序更安全
2.提高代码可读性
方法重写注意点:
- 重写方法名称、形参列表必须与被重写方法的名称和参数列表一致
- 私有方法不能被重写
- 子类重写父类方法,访问权限必须大于等于父类方法的访问权限
- 子类不能重写父类的静态方法
子类继承父类后构造器的特点:
- 子类中所有的构造器默认都会访问父类中无参的构造器,在执行自己
原因:
- 子类在初始化时,有可能会用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类数据
- 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化
如何调用父类构造器
- 子类构造器的一行默认是:super(),不写也存在
this(...)和super(...):
- 子类通过this(...)去调用本类的其他构造器,本类的其他构造器会通过super去手动调用父类的构造器,最终还是会调用父类构造器
- 注意:this(...)和super(...)都只能放在构造器的第一行,二者只能用一个
四种权限修饰符的分类和具体作用范围:
权限修饰符:
修饰符 | 同一个类中 | 同一个包中其他类 | 不同包下的子类 | 不同包下的无关类 |
private | √ | |||
缺省 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
2.语法
1.final
特点:
- final修饰类,类不能被继承
- final修饰方法,方法不能被重写
- final修饰变量,只能赋值一次
注意:
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生改变的
2.常量
- 常量是使用public static final修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变。
- 常量的作用和好处:可以用于做系统的配置信息,方便程序的维护,同时也能提高可读性。
常量命名规范:英文单词全部大写,多个单词下划线连接
常量执行原理
- 在编译阶段会进行宏替换,把使用常量的地方全部替换成真是的字面量
- 这样做的好处是让使用常量的程序执行性能与直接使用字面量是一样的
3.枚举
特征:
- 枚举类都是继承了枚举类型:java.lang.Enum
- 枚举都是最终类,不可以被继承
- 枚举类的构造器都是私有的,枚举对外不能创建对象
- 枚举类的第一行默认都是罗列枚举对象的名称的
- 枚举类相当于是多例模式
枚举做信息标志和分类:
- 代码可读性好,入参约束严谨,代码优雅,是最好的信息分类技术!建议使用!
枚举类用法举例:
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER;
}
public static void main(String[] args) {
Season season =Season.SPRING;
switch (season){
case SPRING:
System.out.println("春天来了~");break;
case SUMMER:
System.out.println("夏天来了~");break;
case AUTUMN:
System.out.println("秋天来了~");break;
case WINTER:
System.out.println("冬天来了~");break;
default:break;
}
}
4.抽象
注意:
- 抽象方法中只有方法签名,不能声明方法体
- 一个类中如果定义了抽象方法,这个类必须声明抽象类,否则报错
- 不能使用abstract修饰变量、代码块、构造器
- 抽象类失去了创建对象的能力
使用场景:
- 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承
- 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类完成。
5.接口
接口是一种规范,接口中只能定义抽象方法和常量。
注:
- 一个类实现接口,必须重写全部接口的抽象方法,否则这个类需要定义成抽象类。
- 一个类可以实现多个接口,一个接口可以继承多个接口
接口中写实现方法
1.默认方法
必须使用default修饰
public interface People {
/**
* 接口实现方法
*/
default void eat(){
System.out.println("吃饭~~");
}
}
public class Student implements People{
public static void main(String[] args) {
Student student = new Student();
student.eat();
}
}
2.静态方法
使用static修饰
必须使用接口本身来调用
public interface People {
static void read(){
System.out.println("读书~~");
}
}
public class Student implements People{
public static void main(String[] args) {
People.read();
}
}
3.私有方法
只能在本类中被其他默认方法或私有方法来访问(JDK1.9才开始支持该方法)
public interface People {
/**
* 接口实现方法
*/
default void eat(){
run();
System.out.println("吃饭~~");
}
private void run(){
System.out.println("跑步~~");
}
}
注意:
一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认使用父类的
一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法