java学习之旅(day.10)

重写

前提:需要有继承关系,是子类重写父类的方法,不是属性

重写特点:

  1. 方法名必须相同,
  2. 参数列表必须相同,否则就变成重载了
  3. 修饰符:范围可以扩大,不能缩小(即父类的private的,可以扩大为public的,但不能反过来)

​ 大小关系:public>protected>Default>private (不写的时候,默认为default)

  1. 重写可能会抛出异常,异常的范围可以被缩小,但不能被扩大

重写:子类的方法和父类的方法必须一致,方法体不同

为什么需要重写

  1. 父类的功能,子类不一定需要或不一定满足,需要进行重写

alt+insert 选中override method

package com.zhang.oop.demo07;
//重写是对方法的重写,和属性无关
public class B {
    public  void test(){
        System.out.println("B=<test");
    }

}
/*
package com.zhang.oop.demo07;

public class A extends B {
    //override 重写
    @Override        //自动生成的注解
    public void test() {
        //super.test();
        System.out.println("A=<test");
    }
    /*public  void test() {//把子类和父类方法中的static去掉就会产生小圆圈,向上向下的箭头(重写)
        System.out.println("A=<test");

    }*/
/*

//删去文本注释的方法,用alt+ insert选 override Method(重写方法)
//}



package com.zhang.oop;

import com.zhang.oop.demo07.A;
import com.zhang.oop.demo07.B;
//重写只跟非静态方法有关,与静态方法无关,重写的关键词只能是public,不能是private
//静态方法和非静态方法区别很大
//加了static的静态方法,调用方法跟左边有关
//未加static的非静态方法
public class Application {
    public static void main(String[] args) {
       //方法的调用只和左边的类型有关(即只与定义的数据类型有关,跟右边的new没有什么关系)
        A a=new A();
        a.test();//走的A的方法 A=<test
        //子类可以指向父类(父类的引用指向了子类)
        //父类B的引用b指向子类A  B=<test
        B b=new A();//子类重写了父类的方法
        b.test();//走的B的方法
    }

}

 */

多态

​ 动态编译,程序类型只有在执行过程才可决定,写代码时确定不了。通过多态使可扩展性更强

​ 即同一方法可以根据发送对象的不同而采用多种不同的行为方式,比如同样都是run方法,但通过s1和s2调用出的确实不同的结果(看程序)

一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多

多态存在的条件

  1. 有继承关系
  2. 子类重写父类的方法
  3. 父类引用指向子类对象

多态是方法的多态,属性没有多态性

多态的注意事项

  1. 多态时方法的多态,属性没有多态
  2. 父类和子类有联系,不要瞎几把转换,无联系,出现类型转换异常ClassCastException
  3. 多态存在的条件:继承关系、方法需要重写,没有重写的话调用的都是各自的,就无区别了
  4. 父类的引用指向子类对象:Person s2=new Student();即father f1=new son();
  5. 方法需要被重写,但存在无法被重写的
  • static方法,静态的,时属于类的,不是实例的(通过static修饰的方法不能被重写)
  • final 是常量的,被其修饰的方法无法去改变它
  • 通过private修饰的方法也不能被重写
package com.zhang.oop.demo08;

public class Person {
    public void run(){
        System.out.println("run");
    }

}
/*
package com.zhang.oop.demo08;

public class Student extends Person {
//在子类中重写一下父类run()方法
    @Override
    public void run() {
        System.out.println("son");
    }
    //再给子类定义一个eat()方法,而不给父类定义eat()方法
    public void eat(){
        System.out.println("eat");
    }
}


package com.zhang.oop;

import com.zhang.oop.demo08.Person;
import com.zhang.oop.demo08.Student;

public class Application {
    public static void main(String[] args) {


//通常情况下,new Student,这个Student类型就已经确定了
        //new了什么就是什么,一个对象的实际类型是确定的(Student),但是可以指向的引用类型就不确定了(Person、Object等)
    Student s1=new Student();

    Person s2=new Student();//父类的引用指向子类的类型
    Object s3=new Student();//Object是所有类的祖宗
    //都是new Student,却可以表示多种状态

        s2.run();//new的是Student,依旧可以用System.out.println("run");输出父类的方法,即子类继承了父类的全部方法
        s1.run();//重写前s1输出run,重写后,子类重写了父类的方法,执行子类的方法s1,s2都输出son

        //再看写了eat方法后能调用吗
        //对象能执行哪些方法,主要看对象左边的类型,而与右边关系不大
        //如s1.eat();左边类型为Student,故可调用Student中的eat方法,而s2左边的类型为Person,再Person中无法调用eat方法,
        // 因为Person中就没有eat方法,故子类和父类指向的引用时不一样的,子类Student可以调用自己的方法和继承过来父类Person的方法,
        //父类Person可以指向子类Student,但是不能调用子类独有的方法
        s1.eat();//此处 s2.eat();无法调用
//插嘴:这里,有点强制转换的内容,把Persong类强制转换为Student类的方法,s2就能调用eat方法了,代码如下
        ((Student)s2).eat();
    }
}
 */

instanceof 类型转换间的关系

instanceof:java中需要判断一个对象是什么类型,instanceof这个关键字可以判断两个类间是否存在父子关系

package com.zhang.oop.demo10;

public class Application {
    public static void main(String[] args) {

        //Object>String
        //Object>Person>Teacher
        //Object>Person>Student

       // System.out.println(x instanceof y);能不能编译通过看x与y之间是否存在父子关系
        //编译后时true还是false看变量,也就是x所指向的实际类型是否为y的子类型
        Object object=new Student();
        System.out.println(object instanceof Student);//true
        System.out.println(object instanceof Person);//true
        System.out.println(object instanceof Object);//true
        System.out.println(object instanceof Teacher);//false
        System.out.println(object instanceof String);//false

        Person person=new Student();
        System.out.println(person instanceof Student);//true
        System.out.println(person instanceof Person);//true
        System.out.println(person instanceof Object);//true
        System.out.println(person instanceof Teacher);//false
        //System.out.println(person instanceof String);//编译时就报错

        Student student=new Student();
        System.out.println(student instanceof Student);//true
        System.out.println(student instanceof Person);//true
        System.out.println(student instanceof Object);//true
       // System.out.println(student instanceof Teacher);编译时就报错
       // System.out.println(student instanceof String);编译时就报错

    }
}

多态

  1. 父类引用指向子类的对象
  2. 把子类转换为父类,直接就可以转换过去
  3. 把父类转换为子类时,需强制转换
  4. 方便方法的调用,减少重复的代码
package com.zhang.oop.demo09;

public class Person {
    public void run(){
        System.out.println("run");
    }
}

/*
package com.zhang.oop.demo09;

public class Student extends Person {
    //此时子类Student中有两个方法,一个是本身的go方法,好友一个时继承父类Person的run方法
    public void go(){
        System.out.println("go");
    }

}


package com.zhang.oop.demo09;

public class Application {
    public static void main(String[] args) {

       //类型之间的转换(父类跟子类),之前学的时基本类型的转换(高转低需要强转,地转高直接转)

       Person student=new Student();//Student student=new Student();为什么可以把它直接变成Person类
      // student.go();无法调用,此处的student是Person类型的,要想实现student.go(想用student的方法)需要将Person类型强制转换为Student类型的,代码如下

        Student student1=(Student) student;
        student1.go();
        //若想用一句话代替上面两行代码如此: ((Student)student).go();
        //再举个例子:
        //子类转换为父类时,可能丢失自己本来的一些方法
        //Student student =new Student();
        //student.go;如果想把上一行的student变成一个Person类型,低转高,不用强制转,如下:
        //Person person=student;
     }
}

 */
posted on 2021-01-10 21:20  懵逼的程序小白  阅读(64)  评论(0)    收藏  举报