目录
一、继承的概念和特点
- 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性的继承父类,必须承接父类所有的可访问的特征。
- Java的继承只能是单继承,子类只能继承一个父类。
- 子类可以访问父类非私有成员。
- 父类不可以访问子类特有的成员
二、方法的重写
方法重载 VS 方法重写
方法重载
- 同一个类
- 方法名相同,参数列表不同(参数顺序、个数、类型)
- 与方法的参数名无关
- 方法返回值、访问修饰符任意
方法重写
- 在子类中定义
- 方法名相同,方法名、参数类型、顺序、个数都要与父类继承的方法相同。
- 方法的参数名不做限制
- 返回值
- 若父类的返回值是void或基本数据类型,子类的返回值类型必须相同
- 若父类的返回值类型是自定义的引用类型,子类的返回值可以是父类的返回值类型或父类返回值类型的子类
- 以上两点,尝试理解一下,第二点很好理解,可以借助后面的多态?待后续完善
- 访问修饰符,访问范围需要大于等于父类的访问范围
- 子类不能重写父类static或final修饰的方法。
举个🌰
若父类有如下方法
public static Fruits create(){
return new Fruits();
}
子类如下写法会报错,因为子类不能重写父类static或final修饰的方法。
@Override //报错:Method does not override method from its superclass
public static Waxberry create(){
return new Waxberry();
}
但是,我们把@Override去掉就可以,这是为啥呢?若父类中有一个静态方法,而子类中有一个方法名、参数列表与之完全一样的静态方法,编译器认为子类只是将父类同名的方法进行了隐藏,而并非是重写,这点很疑惑,不过测了一下,在子类的其他方法中还是可以通过super.create()调用父类的create方法。
当子类重写父类方法后,子类对象调用的是重写后的方法。
虽然重写的概念仅针对方法,但是在子类中是可以定义和父类重名的变量的,当有重名变量时,子类对象调用的子类特有的变量;子类未重新定义变量时,子类对象调用的是父类变量。
父类的构造方法不允许被继承,不允许被重写,但是会影响子类的实例化过程。
三、访问修饰符
四、继承后的实例化顺序
五、super关键字
可以通过该关键字显示的调用父类的方法。
super-代表父类引用
- 访问父类成员方法:super.print();
- 访问父类属性:super.name;
- 访问父类构造方法: super();
super 构造方法
- 子类的构造国臣必须调用其父类的构造方法
- 若子类的构造方法中没有显示标注,则系统默认调用父类无参的构造方法
- 若子类构造方法中既没有显示标注,且父类中没有无参的构造方法,责编以出错。
- 使用super调用父类指定构造方法,必须在子类的构造方法的第一行。
super VS this
- this-当前对象;super-父类对象
- this不能在静态方法中使用,super同样,这很好理解,因为this和super都代表对象,静态方法在没有实例化对象的时候就可以调用,所以他不应该拿对象的东西
- this 和 super不能同时出现在同一个方法中,毕竟都是想抢占第一行位置的大佬
六、Object类
一个类没有使用extends关键字明确标识继承关系,则默认继承Object类(包括数组)
Java中的每个类都可以使用Object中定义的方法。
equals:继承自Object类中的equals方法,比较的是两个引用是否指向同一个对象。
// 重写equals方法,比较两个对象是否相等(比较shape,taste)
public boolean equals(Object obj){
if(obj == null)
return false;
Fruits two = (Fruits)obj;
if((getShape().equals(two.getShape()))&&(getTaste().equals(two.getTaste())))
return true;
return false;
}
toString:在语句中直接输出对象名的时候会自动调用toString方法,输出对象的字符串表现形式:类型信息+@+地址信息。
//重写toString方法,输出的表现形式不同(输出shape,color,taste)
public String toString(){
return "杨梅的信息:果实为" + getShape() + "," + getColor() + "," + getTaste() + "非常好吃!";
}
== 比较的是变量里面存储的值,不过应用类型变量里面存储的是对象的内存地址。所以对于基本类型而言只要值相同就是相等,但是对于应用对象而言需要指向同一块内存空间才可以等。
String类对equals方法进行了重写,比较的是值是否相等,而不是是否指向同一个对象。==表示的是否指向同一个对象。String类也重写了toString。
String str1 = "op56789";
String str2 = "op56789";
System.out.println("str1.equals(str2): " + str1.equals(str2));
System.out.println("str1==str2: " + (str1==str2));
System.out.println("=====================");
String s1 = new String("op56789");
String s2 = s1;
System.out.println("s1.equals(s2): " + s1.equals(s2));
System.out.println("s1==s2: " + (s1==s2));
System.out.println("=====================");
String s3 = new String("op56789");
System.out.println("s1.equals(s3): " + s1.equals(s3));
System.out.println("s1==s3: " + (s1==s3));
输出
str1.equals(str2): true
str1==str2: true
=====================
s1.equals(s2): true
s1==s2: true
=====================
s1.equals(s3): true
s1==s3: false
七、final 关键字
final + class
- 该类没有子类
- 可以写成 public final class 或者 final public class
final + 方法
- 该方法不允许被子类重写,但是可以被子类正常继承调用,子类也可以对该方法进行重载。
- final 不可以修饰构造方法
final + 方法内局部变量
- 只要在具体被使用前进行赋值即可,一旦赋值不允许被修改
- 基本数据类型,赋值之后不能更改
- 引用类型,初始化后不能再只想两一个对象,但对象的内容是可变的。即可以更改该对象的成员属性,但是不能new 一个新对象赋给他。
final + 成员属性
- 定义直接初始化
- 构造方法
- 构造代码块
- 其他位置均不可以赋值,都不能通不过在构造方法中调用set方法,若在构造方法中赋值只能直接this.成员属性=xxx
可配合static使用
- 可修饰方法、变量
使用final修饰可以提高性能,但会降低可扩展性。
八、注解
可以声明在包、类、属性、方法、局部变量,方法参数等的前面,用来对这些元素进行说明、注释。
按照运行机制
- 源码注解
- 只在源码阶段保留,在编译阶段丢弃,例如@Override
- 编译时注解
- 在编译时期保留,在加载class文件时会被丢弃,例如:Spring框架的@NotNull
- 运行时注解
- 在运行阶段还起作用,甚至会影响运行逻辑的注解,例如:Spring框架的@Autowride
按照来源划分
- 来自JDK的注解
- 来自第三方的注解
- 我们自己定义的注解
元注解
- 用来定义注解的注解,会对注解进行标注,例如:@Target-用来限制注解可以用在什么地方
参考:慕课网-Java工程师课程