Java SE 面向对象 多态

Java SE 面向对象 多态

1.、访问控制符

指被不同权限修饰符修饰的内容能够被使用的范围

关键字本类同个包中不同包的子类所有类
private
default
protected
public

注意:

  • 使用最多的private,public

  • 能够修饰类的权限修饰符: public ,default(默认的省略不写)

  • 都是成员修饰符,只能修饰成员,不能修饰局部

  • 不能在外部调用一个作用域中的局部内容(局部变量)

  在不同包下的子类中,如果想要使用父类中被protected修饰的成员,需要通过继承关系使用(直接在子类使用有权限的父类成员,或者通过子类对象使用).不能通过父类对象是使用

2、方法重写(override)

  在子类继承父类后,继承了一写功能方法,有些功能,功能的实现不满意,可以进行功能的重写(重新实现)

重写定义方法体

  • 不同的两个类
  • 继承关系|实现关系
  • 方法签名相同(方法名+参数列表)

使用:

  • 子类一旦重写方法,子类对象调用的时候,就会发生就近原则,对父类方法进行屏蔽

  • 子类对象调用功能时候,子类存在找子类,子类没有找父类

== <= >=满足的条件:

  • == : 方法签名完全相等
  • <= : 返回值类型为基本数据类型要求完全相等,如果为引用数据类型,子类方法返回值类型<=父类方法的返回值类型
  • >= : 权限修饰符: 子类方法的权限修饰符>=父类方法的权限修饰符

检查是否为重写方法:

  • 1.@Override 强制检查是否为重写方法,不是报错
  • 2.工具中方法的左侧有提示

不能被重写的方法:

  • 1.被private关键字修饰的方法不能被重写
  • 2.被final关键字修饰的方法不能被重写
  • 3.被static关键字修饰的方法不能被重写

子类中出现于父类静态方法同名的方法时候,子类的同名方法也要是静态的,否则报错,但是不是重写方法

public class OverrideDemo02 {
    public static void main(String[] args) {
        ErEr er=new ErEr();
        System.out.println(er.name);
        // 调用 父类
        er.test();
        er.run();
    }
}
class YeYe{
    String name="YeYe";
    public void test(){
        System.out.println("Yeye");
    }
}

class BaBa extends YeYe{
    String name="baba";
    //  重写test方法
    public void test(){
        System.out.println("baba");
    }
    public void run(){
        System.out.println("名言");
    }
    //静态方法
    public static void haha(){
        System.out.println("haha");
    }
}

class ErEr extends BaBa {
    String name="erer";
    //重写父类方法
    public void run(){
        System.out.println("都没我有钱");
    }
}

3、Object 类

老祖宗类 java.lang

  • java中所有类的父类
  • java中的所有类都会直接|间接的继承自Object类
  • 如果没有显示的继承自某个类型,默认会继承Object

ctrl+n->查询某个类

public class Person { ... }

等价于 :

public class Person extends Object { ... }

3.1 equals ()方法

1、equals() 比较两个对象是否相等(默认使用==比较,比较对象地址)
   如果想要实现比较对象内容,而非地址值,需要在子类中重写equals方法,需要自己实现比较内容(成员属性的值)

public boolean equals(Object obj) {
        return (this == obj);
    }

== :
   比较基本数据类型: 比较数据值
   比较引用数据类型: 比较两个对象的地址是否相等

注意:

  • 认为两个对象,如果所有成员属性的值都想等,就应该是一个对象
  • 在java中只要通过new关键字创建的对象,无论成员属性值是否相等,地址都不相等,如果比较地址,都不相等,所以引用数据类型对象的时候,不让它默认比较地址,手动让她比较内容
public class ObjectDemo01 {
    public static void main(String[] args) {
        Fu fu = new Fu();
        Fu fu2 = fu;

        System.out.println(fu == fu2);  //true
        System.out.println(fu.equals(fu2)); //true

        String str1 = "zhangsan";
        String str2 = "zhangsan";

        System.out.println(str1.equals(str2)); //true

        Person1 p1 = new Person1("haha",20,1001);
        Person1 p2 = new Person1("haha",30,1001);

        System.out.println(p1 == p2); //比较地址  false
        System.out.println(p1.equals(p2)); //比较num内容 true
        System.out.println(p1.equals(new String())); //比较地址  false

    }
}

class Fu{}

class Zi extends Fu{}
public class Person1 {
    public String name;
    public int age;
    public int num;  //身份证号
    //空构造
    public Person1(){  }
    public Person1(String name,int age,int num){
        this.name = name;
        this.age = age;
        this.num = num;
    }

    //重写equals  要求: 只比较两个人的身份证号决定两个Person是否相等
    public boolean equals(Object obj) {//Object obj =  new Person("yinwei",20,1001);  多态引用只能调用父类中存在的成员
        //获取当前对象的num
        int num1 = this.num;
        //获取参数对象的num
        if(obj instanceof Person1){
            Person1 p = (Person1)obj;
            int num2 = p.num;
            if(num1==num2){
                return true;
            }
        }
        return false;
    }
}

3.2 toString() 方法

  • toString() 以字符串的形式表示当前对象

    • Object类中的toString默认返回当前对象类型的包名.类名@十六进制的地址值

    • 如果想要打印对象的成员变量的值不想打印对象地址,可以在子类中对toString方法进行重写

注意:

  当**打印一个对象的引用的时候,默认会调用toString,**打印的是当前对象调用了toString之后的返回值。

ublic class ToStringDem06 {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();

        s1.name = "zhangsan";
        s1.age = 19;

        System.out.println(s1);
        System.out.println(s1.toString());
    }
}

class Student{
    public String name;
    public int age;

    //需求:打印对象引用时候,输出当前对象的所有成员变量的值
    public String toString(){
        return name+"-->"+age;
    }
}

4、多态

一种事物的多种形态|多种表现形式

  • 多态的前提: 继承|实现
  • 多态的最终体现: 父类的引用指向子类的对象
//多态  父类引用指向子类对象
Baa ba2 =new Zii();

3.1 使用

  ​ 当父类类型的引用调用成员时候:

成员变量: 编译运行看父类|左边|类型

成员方法:

​ 编译看父类|类型|左边
运行时找父类方法,方法被重写找子类

  当通过父类的引用调用成员方法时候,如果 子类有重写方法就调用重写的, 如果没有找父类
如果多态不配合方法的重写,多态也没有意义

public class PolymerDemo03 {
    public static void main(String[] args) {
        Baa baa=new Baa();
        Zii zii =new Zii();

        //多态  父类引用指向子类对象
        Baa ba2 =new Zii();
        //调用 父类 属性
        System.out.println(ba2.name);
        //调用子类重写方法
        //多态不配合方法的重写,多态也没有意义
        ba2.test();
        //父类自己方法
        ba2.test1();
    }

}

class Baa{
    String name="Baba";

    public void test(){
        System.out.println("父类哈哈");
    }
    public void test1(){
        System.out.println("第二bab类");
    }

}
class Zii extends Baa{
    String name="zii";
    public void test(){
        System.out.println("子类哈哈");
    }
}

3.2 向上转型和向下转型

基本数据类型的类型转换 == 引用类型的类型提升

  • 向上转型 : 自动类型提升
       从小到大->从子类到父类
       父类类型 引用 = new 子类类型();
       long l = 1;
			//多态 向上转型
        Die die=new Zi();
  • 向下转型 : 强制类型转换
       从大到小 ->从父类到子类
       小范围类型 变量 = (小范围类型)大范围类型的数据;
       int i = (int)l;

向下转型可能遇到类型转换异常ClassCastException:

  • 引用 instanceof 类型
       判断前面的引用是否指向后面类型的对象,或者是否指向后面类型子类的对象,如果是返回true,不是返回false

    //转型之前的判断: 为了预防类型转换异常的出现  引用 instanceof 类型
            //向下转型
            Zi zi =(Zi)die;
    
public class CastDemo04 {
    public static void main(String[] args) {
        //多态 向上转型
        Die die=new Zi();
        System.out.println(die.name);
        die.run();

        //转型之前的判断: 为了预防类型转换异常的出现  引用 instanceof 类型
        //向下转型
        Zi zi =(Zi)die;
        zi.play();
        zi.run();

        System.out.println(die instanceof Die);  //false
        System.out.println(die instanceof Zi); //true
        //System.out.println(die instanceof KongZiDie);  //true

    }
}
class Die {
    String name="Die";

    public void run(){
        System.out.println("Die");
    }
}
class Zi extends Die{
    String name="Er";

    public void run(){
        System.out.println("Er");
    }
    public void play(){
        System.out.println("yuanshen");
    }
}

3.3 多态与继承联系

  • 多态:成员变量看父类,方法看父类,子类重写看子类
  • 继承:继承父类变量和方法,子类重写看子类

四大原则 :

  • 一、继承链:自己没有找父
  • 二、 编译看类型、确定方法,运行找对象
  • 三、就近最优原则
  • 四、父类引用对子类新增方法不可见
public class PolyTest05 {
    public static void main(String[] args) {
        A a1=new A();//A and D  A and A
        A a2=new B();//A and D  B and A
        B b =new B();//B and B  B and A  A and D
        C c=new C();//B and B  B and A  A and D
        D d =new D();//B and B  B and A  A and D
        System.out.println(a1.show(b)); //A and A
        System.out.println(a1.show(c)); //A and A
        System.out.println(a1.show(d)); //A and D
        System.out.println(a2.show(b)); //B and a
        System.out.println(a2.show(c)); //B and a
        System.out.println(a2.show(d)); //a and d
        System.out.println(b.show(b));  //B and B
        System.out.println(b.show(c));  //B and B
        System.out.println(b.show(d));  //a and d
    }

}

class A{
    public String show(D obj){
        return ("A and D");
    }
    public String show(A obj){
        return ("A and A");
    }
}

class B extends A{
    public String show(B obj){
        return ("B and B");
    }
    public String show(A obj){
        return ("B and A");
    }
}

class C extends B{
}

class D extends B{
}

5、abstract 抽象的

  • 抽象类: abstract修饰的类

  • 抽象方法: 被abstract修饰的方法

    • 可以没有方法体
    • 必须存在与抽象类中

注意:

  • 1.抽象类不能够实例化

  • 2.抽象方法必须存在抽象类中

  • 3.抽象类中可以存在抽象方法,可以存在普通的具体方法,可以存在成员,构造器

  • 4.抽象方法必须要被重写才能使用

  • 5.抽象方法只要被重写就可以使用,不需要再次重写,可以根据需求进行重写

  • 6.抽象类使用: 通过具体子类的对象调用

    • 1.普通的子类: 需要重写所有抽象方法+按需新增
    • 2.抽象子类: 按需重写抽象方法+按需新增
  • 7、abstract 不能与private,static,final,native同时存在

public abstract class Develop01 {
    //工作  方法体不确定些什么,不确定怎么写,那就不写
    public abstract void work1();
    public abstract void work2();

    //普通方法
    public void sleep(){
        System.out.println("边工作边休息...");
    }
}
/*
    java攻城狮
        普通的子类|具体的子类(没有被abstract修饰的类)
 */
public class Java extends Develop{
    //对父类中继承的抽象方法进行重写实现
    @Override
    public void work1() {
        System.out.println("JAVA按照规矩办事!!!");
    }

    @Override
    public void work2() {
        System.out.println("JAVA做后端开发...");
    }

    //形象  -->新增方法
    public void xingxiang(){
        System.out.println("没头发了!!!!又该植发了!!!!!");
    }
}
public class AbsTest {
    public static void main(String[] args) {
        //抽象类不能实例化
        //Develop de = new Develop();

        //具体子类的使用
        Java java = new Java();
        java.work1();
        java.work2();
        java.xingxiang();
        java.sleep();
        
        //抽象类的多态 : 向上转型
        //只能调用develop类中的功能
        Develop d = new Java();
        d = new Web2();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值