方法覆盖(重写):
子类中可以定义和父类一模一样的方法
在子类中访问这个一模一样的方法,访问到的是子类中定义的方法
在父类中访问这个一模一样的方法,访问到的还是子类定义中的方法
子类中的方法在调用的时候(对象才能调用):
1、在子类自己定义的方法中查找调用的目标方法,如果找到就执行
2、如果在子类自己定义的方法中没找到目标方法,才会在父类定义的方法中 查找调用的目标方法。
对于父类中的方法调用而言,查找目标方法的过程和子类中方法的查找过程一模一样
1、先在子类中查找,如果找到就执行
2、如果子类中找不到,此时再去父类中查找。
上诉两种情况针对的都是子类对象调用方法的时候,如果调用的是子类方法,则是第一种情况,如是调用的父类方法,则是第二种情况,但两种情况都是先去子类中查找
public class Demo1 {
public static void main(String[] args) {
//OverrideSon1 son = new OverrideSon1();
// 测试在子类类体中,访问子类和父类定义的一模一样的方法
//son.callSameMethod(); //son
// 测试在父类类体中,访问子类和父类定义的一模一样的方法
//son.call(); // son
//测试在子类中能否既访问到子类中定义的一模一样的方法,也访问到父类中定义的一模一样的方法
//son.callAll();
//
//OverrideSon2 son2 = new OverrideSon2();
//son2.callSameMethod();
//son2.call();
//son2.callAll();
//只有在 子类对象上调用方法 的时候,才会出现
//1. 在子类对象对应的子类类型中找目标方法
//2. 如果没找到,在到父类中找
//如果对于非子类对象
//OverrideFather overrideFather = new OverrideFather();
//overrideFather.sameMethod();
//我能不能在父类中,访问到子类中的成员变量的值呢?
OverrideSon1 overrideSon1 = new OverrideSon1();
overrideSon1.test();
}
}
class OverrideFather {
private int i = 100;
//父类中和子类定义的一模一样的方法
public void sameMethod() {
System.out.println("father");
}
public void call() {
sameMethod();
}
/*
通过方法覆盖,可以让父类,访问到子类中定义的同名成员变量的值
*/
public void test() {
// 1. getI() 返回成员变量i的值
// 2. 子类中的getI()方法返回的是子类对象的i值,父类中的getI方法返回的是父类中的i值
// 3. 方法覆盖就产生了,在父类中调用的getI(), 实际调用到的是子类中定义的get()
System.out.println(getI());
}
public int getI() {
return i;
}
}
class OverrideSon1 extends OverrideFather {
int i = 1000;
//父类中和子类定义的一模一样的方法
public void sameMethod() {
System.out.println("son");
}
public void callSameMethod() {
//在子类中,通过方法名,调用子类和父类中定义的一模一样的方法
sameMethod();
}
public void callAll() {
sameMethod(); //直接访问到的是子类中自己定义的一模一样的方法
//调用父类中定义的一模一样的方法
super.sameMethod();
}
public int getI() {
return i;
}
}
class OverrideSon2 extends OverrideFather {
//父类中和子类定义的一模一样的方法
public void sameMethod() {
System.out.println("son 2");
}
public void callSameMethod() {
//在子类中,通过方法名,调用子类和父类中定义的一模一样的方法
sameMethod();
}
public void callAll() {
sameMethod(); //直接访问到的是子类中自己定义的一模一样的方法
//调用父类中定义的一模一样的方法
super.sameMethod();
}
}
子类方法覆盖父类方法的条件:
1、方法的权限满足的条件:子类方法的访问权限不能小于父类的访问权限
2、方法的返回值类型:a、子类方法返回值类型和父类返回值类型相同
b、当父类方法的返回值类型,是引用类型的时候,如 果子类方法的返回值类型是父类返回值类型的子类 类型
3、方法签名必须一致。
public class Demo2 {
public static void main(String[] args) {
MySon mySon = new MySon();
//mySon.test();
MyFather myFather = new MyFather();
//myFather.test();
mySon.test();
}
}
class MyFather {
public void test() {
//method(10, null);
privateMethod();
}
A method(int a, A aa) {
System.out.println("MyFather");
return null;
}
private void privateMethod() {
System.out.println("father privateMethod");
}
public static void staticMethod() {
System.out.println("MyFather staticMethod");
}
}
class MySon extends MyFather {
//如果说我们在方法上放了override注解,其实告诉编译器,
@Override // 该方法要覆盖父类中的方法,
B method(int b, A bb) {
System.out.println("MySon");
return null;
}
//@Override
public void privateMethod() {
System.out.println("son privateMethod");
}
// @Override
public static void staticMethod() {
System.out.println("MySon staticMethod");
}
}
class A {
}
class B extends A {
}
方法覆盖的意义:在子类中,修改父类的方法实现,所谓修改父类被覆盖方法的实现,并没有物理修改父类的方法实现,只是让实际调用的时候调用了子类中的方法,看起来就像父类的方法被修改了。
注意事项:1、private修饰的方法不能被覆盖。
2、静态方法不能被覆盖
final关键字:final是最终的意思,可以修饰类、变量、成员方法
修饰类,类不能被继承
修饰变量,变量就变成了常量,只能被赋值一次
常量包括字面值常量和自定义常量,这里被 final 修饰的变量就是自定义常量。
修饰方法,方法就不能被覆盖。
***其中修饰变量分两种情况:***1、修饰局部变量的时候,必须保证局部变量在使用之前被赋一次值
2、修饰成员变量的时候,必须保证在对象创建完成之前,我们必须通 过代码给final修饰的成员变量赋值一次,这里所谓的赋值一次不 包括 jvm 赋予默认初值的那一次。
public class Demo1 {
public static void main(String[] args) {
A a = new A();
//A a1 = new A(10);
//有一个小点
final A finalLocal = new A();
// 被一个final修饰的引用变量,它指向的对象本身数据是可变的
finalLocal.setIntValue(88);
System.out.println(finalLocal.getIntValue());
//被final修饰的引用变量,不可变的仅仅只是这个引用变量本身的值
//finalLocal = a;
}
}
// 被final修饰的类无法被继承
//final
class A {
final int finalValue1 = 1;
final int finalValue2;
final int finalValue3;
private int intValue;
{
finalValue3 = 200;
}
public A () {
finalValue2 = 100;
}
/*
如果要用构造方法给final修饰的成员变量赋值
必须保证,每个构造方法中,必须给这个final修饰的成员变量赋值赋予初值
*/
public A (int i) {
//
finalValue2 = 90;
}
public final void testFinal() {
final int a = 10;
// 被final修饰的局部变量,只能在使用前辈赋值一次
// a = 100;
System.out.println(a);
}
public int getIntValue() {
return intValue;
}
public void setIntValue(int intValue) {
this.intValue = intValue;
}
}
class B extends A {
// 被final修饰的方法不能被覆盖
//public void testFinal() {
//
//}
}