1.Super
1.1是什么
Super:在当前对象中,表示当前对象的父类。
官方说法是:超在子类中代表了父类型特征。
1.2能做什么
1.用于成员方法/构造方法中,区分子类和父类同名的属性
2.用于子类构造方法中,调用父类的构造方法
super(xxx);必须写在构造方法的第一行
this(xxx)也必须在第一行,所以 他们两个不能同时出现
如果子类构造方法中,没有 this(xxx)也没有 super(xxx) 则 默认有一个 super() 调用父类无参构造
this 和 super 都不能在静态上下文中使用
1.3怎么用
public class Super_01 {
public static void main(String[] args) {
SubClass sub = new SubClass();
sub.m2();
}
}
class SuperClass {
int age = 1;
public void m1() {
}
}
class SubClass extends SuperClass {
int age = 2;
public void m2() {
System.out.println(super.age);
System.out.println(age);
}
}
1.4调用父类
class SupClass_1 {
public SupClass_1(int a) {
System.out.println("父类构造方法");
}
}
class SubClass_1 extends SupClass_1 {
public SubClass_1() {
// super();
super(1);
System.out.println("子类构造方法");
}
}
1.5 注意
1.this()和 super()不能同时出现,都必须写在构造方法第一行
2.this和super 都不能在静态上下文中使用
3.如果构造方法私有化,则不能有子类,因为子类构造方法中需要调用父类构造方法
public class Super_03 {
private Super_03() {
}
}
// class Test extends Super_03{
class Test {
public static void main(String[] args) {
// 由于构造方法私有化,所以其他类中无法创建他的对象
// 因为创建对象,需要调用构造方法
// Super_03 s = new Super_03();
}
Test() {
// 由于构造方法私有化,所以无法继承
// 因为子类构造方法中需要调用父类构造方法
super();
}
}
1.6实例语句块和构造方法
实例语句块:创建对象之后,立刻执行
this()和 super() 不能同时出现
public class Super_04 {
public static void main(String[] args) {
// 父类静态 , 子类静态 , 父类实例 , 父类构造 , 子类实例 , 子类构造
SubClass_2 s = new SubClass_2();
}
}
2.覆写Override
2.1是什么
子类继承父类之后,必须要和父类一模一样吗?
不需要
1 子类可以拥有自己特有的属性
2 子类也可以对父类已有功能进行重写当父类功能无法满足子类需求的时候,需要根据需求对功能进行覆写
覆写特指成员方法
2.2应用场景
覆写场景
当父类功能无法满足子类需求的时候,需要根据需求对功能进行覆写
覆写条件
1 有继承关系的体系中
2 方法名、参数列表、返回值 必须相同
3 重写之后不能比原方法拥有更低的访问权限,访问权限必须是大于等于原方法
4 重写之后不能比原方法拥有更宽泛的异常,异常必须是小于等于原方法
5 只有成员方法可以覆写
覆写的意义:
1 使功能得到增强,可以满足子类需求
2 使用范围原来越广(访问权限)
3 错误越来越少(异常)
public class Override_01 {
public static void main(String[] args) {
Cat c = new Cat();
c.eat();
}
}
class Animal{
public void eat(){
System.out.println("动物吃东西");
}
}
class Cat extends Animal{
// @Override 注解 , 可以加可以不加,只是一种提醒机制,防止出现覆写的语法错误
// 而且是一个源码注解,在编译生成class文件的时候,就会把这个注解自动删除
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
3.final
3.1是什么
final 是修饰符,表示最终的,不可更改的
3.2能做什么
final修饰的类,不能被继承
final修饰的成员方法,不能被覆写
final修饰的变量,没有默认值,不能二次赋值!
而且 final一般用于修饰静态变量,public static 类型 变量名; 又称为常量
3.3怎么用
3.4深入final
public class Final_02 {
public static void main(String[] args) {
final Test t = new Test("张三");
// final 修饰的引用类型
// 是对应变量的值不能修改,但是跟变量指向的堆内存对象中的数据,没有关系
// 是t 使用final修饰,并不是name使用final修饰
// 所以 t的值不能修改,但是跟t指向的对象中的name 没有关系,
t.name = "李四";
System.out.println(t.name);
// 不能二次赋值
// t = null;
}
}
class Test {
String name;
public Test(String name) {
this.name = name;
}
}
4.多态
4.1相关知识
软件设计六大原则
里氏替换原则:能使用父类的地方,就一定可以使用子类
具体链接如下:百度安全验证https://baijiahao.baidu.com/s?id=1645013441658118287&wfr=spider&for=pc
4.2是什么
多态:多种形态,可以做出不同的响应
java中提供了两种多态机制
1 编译时多态:属于静态多态,主要是指方法重载,在调用的时候,可以根据不同的参数,做出不同的响应
2 运行时多态:属于动态多态,主要是指动态绑定来实现的,主要靠子类和父类直接的方法覆写来完成
多态:父类引用指向子类对象!
父类:继承的父类 extends
引用:引用类型变量,保存的是内存地址
指向:就是可以找到谁,保存的是谁
子类对象:就是new的子类实例化对象
父类类型创建的引用类型变量,可以找到子类的对象!父类 变量 = new 子类(); 多态
4.3怎么用
多态的形式:(只要是父类变量保存了子类对象,都是多态)
1 直接赋值 父类 变量 = new 子类();
2 实参和形参:参数列表使用父类声明,但是调用方法时,传入的是子类对象
3 返回值:返回值类型是父类类型,但是返回的对象是子类的对象
public class Poly_01 {
public static void m1(SupClass sup) {
}
public static SupClass m2() {
return new SubClass();
}
public static void main(String[] args) {
// 直接多态
SupClass sup = new SubClass();
// 实参形参多态
m1(new SubClass());
// 返回值多态
SupClass result = m2();
// 多态
SupClass sub = new SubClass();
// 父子类都有的变量, 执行父类 2
System.out.println(sub.a);
// 父类没有的,子类特有属性,调用不了
// System.out.println(sub.b);
// sub.m2();
// 父类子类都有的成员方法,执行子类(方法覆写)
sub.m1();
// 父类有,子类没有,执行父类
sub.m3();
}
}
class SupClass {
int a = 2;
public void m1(){
System.out.println("父类m1");
}
public void m3(){
System.out.println("父类m3");
}
}
class SubClass extends SupClass {
int a = 22;
int b = 33;
public void m1(){
System.out.println("子类m1");
}
public void m2(){
System.out.println("子类m2");
}
}
4.4应用场景和优点
某个需求,只会有一种解决方案,则不需要多态
但是一旦有两种及以上的解决方案,就一定是多态
public class Poly_02 {
public static void main(String[] args) {
User user = new User();
Cat cat = new Cat();
Pig pig = new Pig();
Dog dog = new Dog();
user.eat(cat);
user.eat(dog);
user.eat(pig);
}
}
// 用户类
class User {
// public void eat(Cat cat){
// cat.eat();
// }
// public void eat(Dog dog) {
// dog.eat();
// }
public void eat(Animal animal) {
animal.eat();
}
}
class Animal {
public void eat() {
}
}
// 猫类
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
// 狗类
class Dog extends Animal {
public void eat() {
System.out.println("狗吃肉");
}
}
// 猪类
class Pig extends Animal {
@Override
public void eat() {
System.out.println("猪拱白菜");
}
}
4.5缺点
丢失子类特有的属性
4.6多态进行属性调用
1 如果父类和子类都没有,肯定报错,没法访问
2 如果父类有,子类没有,调用父类的
3 如果父类有,子类也有,除了成员方法执行子类,其他均执行父类
4 如果父类没有,子类有,报错,调用不了,丢失子类特有的属性
public static void main(String[] args) {
SupClass sub = new SubClass();
// 父子类都有的变量, 执行父类 2
System.out.println(sub.a);
// 父类没有的,子类特有属性,调用不了
// System.out.println(sub.b);
// sub.m2();
// 父类子类都有的成员方法,执行子类(方法覆写)
sub.m1();
// 父类有,子类没有,执行父类
sub.m3();
}
}
class SupClass {
int a = 2;
public void m1(){
System.out.println("父类m1");
}
public void m3(){
System.out.println("父类m3");
}
}
class SubClass extends SupClass {
int a = 22;
int b = 33;
public void m1(){
System.out.println("子类m1");
}
public void m2(){
System.out.println("子类m2");
}
}