2、继承

1. 继承

  • 关键字 extends
  • Java中只有单继承
  • final修饰的类无法被继承
  • 静态方法(类方法)不能被继承,静态成员不能被子类访问
  • 子类可以创建新的方法,父类无法调用
  • 子类在被加载前父类先被加载,也就是子类构造时父类先被构造了

2. 修饰符和使用技巧

同一个类内 同包不同类 不同包子类 不同包非子类
public
protected ×
默认 × ×
private × × ×
  1. 凡是打算让子类继承的成员和方法,都用protected修饰
  2. 不打算让包外引用的成员和方法,不写任何修饰符

3. 构造方法的执行顺序

JVM对于有继承关系的类的构造方法,先从当前类开始,根据继承关系,追溯到最开始的祖先类,然后再沿着继承关系向下,逐个执行构造方法。子类的所有构造方法都会默认执行父类无参构造方法,如果父类不存在无参构造,则需要我们自己调用其它构造方法

public class Son extends Father {
    public Son(){
   //这句话是执行父类的无参构造方法,实际上默认是存在的,可以不写,但是如果父类没有无参构造方法,就需要我们自己写上去并且调用相应的构造方法,比如:super(1,1)双参构造
        super();	
    }
}

注意:super();语句必须是构造方法的第一句,且其只能出现在构造方法中。

4. 成员的覆盖语法和规则

父类:

public class Parent {
	public int i = 0;
	
	public Parent() {
	}
}

在子类中调用i:

我们发现这个i此时是父类的i

当我们在子类中定义同名i时:

我们发现此时的i变成了当前类的i

其实父类中用int定义的i只是被隐藏了,我们想要去调用它可以用super.i

这时的两个i分别是子类和父类的

当我们再建一个新类Me去继承Son类

我们发现此时Parent类中被隐藏的i出现了,因为Son类中的i是private的,无法被继承,那么我们的Me会自动寻找更高层是否有存在的可继承的同名属性(i)

5. 方法的重写——主要的覆盖手段

  1. 方法覆盖只存在于有继承关系的类之间
  2. 子类中覆盖父类方法的方法里,返回值类型,方法名,参数列表必须相同,否则,若方法名相同其他的不完全相同,就是方法重载
  3. 子类方法修饰符不能低于父类方法(否则重写的意义何在,我们调用时会调用不到它)

5.1 重写和重载的区别

区别:

  1. 重载实现的是编译时的多态性,而重写实现的是运行时的多态性。

  2. 重载发生在一个类中,同名的方法的参数列表要不同;而重写发生在子类与父类之间,重写方法的重写方法要相同。

  3. 重载方法的返回类型可以修改,而重写方法不能。

  4. 重载方法的异常可以修改,重写方法的异常可以减少或删除,一定不能抛出新的或者更广的异常。

  5. 重载方法的访问可以修改,而重写方法的访问一定不能做更严格的限制

6. 基类与派生类之间的强制类型转换

public class Parent {
	public int i = 0;
	
	public Parent() {
	}
	
	void hello() {
		System.out.println("I am father");
	}
}

public class Son extends Parent {
	private double i = 0;
	
	public Son() {
		
	}
	
	void hello() {
		System.out.println("I am son");
	}
}
public class Test {

	public static void main(String[] args) {
		Son son = new Son();
		Parent parent = (Parent)son;
		parent.hello();
		
		Parent parent2 = new Son();
		parent2.hello();
	}

}

输出结果:

对象类型约束对象所能引用的成员和方法,但是不能更改成员和方法的本质内容;对于方法,强转不能改变其所实际指向的代码的首地址(son.hello()这个方法本质上指向的是Son这个类里面定义的hello方法,即使改变了其类型,方法指向不变,所以运行的代码是Son里面的代码,并非Parent)

注意:基类对象无法强转为派生的,JVM会在运行时报错,原因自己想

7. 重写toString()方法

诸如System.out.println()等方法,其在对非八大基本类型的对象处理时,对自动调用对象里面的toString方法,就拿这个方法举例:

System.out.println(cat) 等价于 System.out.println(cat.toString())

所以我们在覆盖toString()方法后,就能实现我们要的输出或者其他操作了,若我们不覆盖,JVM会自动调用默认的toString()方法,就是 ''类类型全程@首地址'' 字符串的样式

8. 重写equals()方法

8.1 对象比较方式

八大基本类型外的类对象的比较有两种方式:

  1. 用 == 比较

    ==在Java中比较的是对象首地址

  2. 对象1.equals(对象2)的方法比较

    默认实现也是比较对象首地址,我们可以重写这个方法

8.2 重写步骤

  1. 判断条件是否是null,return false

  2. 是否为同一个对象(指的是自己,比如:a.equals(a)),return true

  3. 是否为除了这两个之外的其他类,return false

  4. 然后再将参数里面的obj强转为我们当前类

  5. return 比较条件

    比如:

	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Son other = (Son) obj;
		return Double.doubleToLongBits(i) == 			   			  Double.doubleToLongBits(other.i);
	}

9. final关键字

  1. 修饰类,这个类不允许被继承
  2. 修饰方法,这个方法不能被子类重写
  3. 修饰成员,让成员的空间变为''只读'',即“常变量”
posted @ 2023-03-05 22:44  Geek李  阅读(36)  评论(0)    收藏  举报