Java笔记(八)

目录

父类引用指向子类对象(向上转型)

父类引用转为子类对象(向下转型)

抽象类和抽象方法

抽象方法

抽象类

抽象类的使用要点

接口

接口的成员特点

抽象类和接口的区别


父类引用指向子类对象(向上转型)

Animal a = new Cat();

//父类为Animal ,子类为Cat

//声明的是父类,实际指向的是子类的一个对象

它表示定义了一个Animal类型的引用,指向新建的Cat类型的对象。由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向Cat类型的对象的。这就是“向上转型”。 

要知道,父类对象不可以访问子类成员变量(属性,方法)。而向上转型,则用父类引用指向子类对象,来对子类继承父类的属性和方法,以及子类重写的方法或属性进行访问。

因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特, 定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。

class Father{
    
    public void sleep(){
        System.out.println("Father sleep");
    }
 
    public void eat() {
        System.out.println("Father eat");
    }
}
 
class Son extends Father {
    
    public void eat() {
        System.out.println("son eat");//重写父类方法
    }
    
    //子类定义了自己的新方法
    public void newMethods() {
        System.out.println("son method");
    }
}
 
public class Demo {
 
    public static void main(String[] args) {
        
        Father a = new Son();
        a.sleep();//sleep方法只有father类有写,并且子类没有重写
        a.eat();
        
        //a.methods();    /*报错:The method methods() is undefined for the type Father*/
    }
}

 1、a实际上指向的是一个子类对象,所以可以访问Son类从Father类继承的方法sleep()和重写的方法eat()
2、由于向上转型,a对象会遗失和父类不同的方法,如methods();
简记:A a = New B()是new的子类对象,父类的引用指向它。儿子自己挣的东西,父亲不能访问。(向下转型可以解决这个问题,后面会提),父亲给儿子留下的(extends)或者儿子重写父亲的东西,父亲才能访问
答案:
Father sleep
son eat

父类引用指向子类对象,有以下几种情况

  • 如果子类重写了父类的某个方法,那么此时调用的是子类重写的方法
  • 如果子类没有重写父类的某个方法,那么此时调用的是父类中的方法
  • 如果子类中用新增父类中没有的方法,那么这个父类引用是不能调用这个仅在子类中存在的方法的,因为子类对象自动向上转型为了父类对象。(这时可以运用到向下转型的方法)
  • 如果子类和父类有同名的成员变量和静态变量,那么由于子类自动向上转型为父类对象,此时调用father.a,那么输出的必然是父类的成员变量或静态变量,这里不存在子类覆盖父类同名变量这一说,因为这里本身可以看做是一个父类对象
  • 如果Son son=new Son();那么这就是实实在在的子类对象,那么son.a和son.b这样就会覆盖父类的同名变量,输出的是子类的成员变量或静态变量,如果子类没有同名变量,那么son.a和son.b调用的是父类的a和b。换句话说,也就是子类可以继承父类的成员变量和静态变量,同时可以覆盖父类的成员变量和静态变量。

注:

  1. 编译通过只代表语法正确而已,但不代表程序能够跑起来。
  2. 多态的形式(向上转型)访问成员变量,编译和运行都是看等式左边。
  3. 多态的形式(向上转型)访问成员方法,编译看左边,运行看右边。
  4. 多态不能使用子类中特有的功能,但是多态中的向下转型可以帮我们实现。

父类引用转为子类对象(向下转型)

多态 不能使用子类中特有的功能,但是多态中的转型可以帮我们实现。

如果想调用运行类型的特有功能,只有进行强制类型转换,否则通不过编译器的检查。

在向下转型的过程中,必须将引用变量转成真实的子类类型(运行时的类型),否则就会出现类型转换异常(ClassCastException)

Object obj=new String("朴彩英");
//真实的子类类型是String类型,但是此处向下转型为StringBuffer
//StringBuffer str=(StringBuffer)obj;这是错误的
String str=(String)obj;//这才是正确的向下转型方式

class Father{
    
    public void sleep(){
        System.out.println("Father sleep");
    }
 
    public void eat() {
        System.out.println("Father eat");
    }
}

 
class Son extends Father {
    
    public void eat() {
        System.out.println("son eat");//重写父类方法
    }
    
    //子类定义了自己的新方法
    public void newMethods() {
        System.out.println("son method");
    }
}

 
public class Demo {
 
    public static void main(String[] args) {
        
        Father a = new Son();
        a.sleep();
        a.eat();
        //a.methods();    /*报错:The method methods() is undefined for the type Father*/
        Son x=(Son)a;
        x.newMethods();//进行向下转型后即可访问子类中特有的methods方法
    }
}

1、a实际上指向的是一个子类对象,所以可以访问Son类从Father类继承的方法sleep()和重写的方法eat()
2、由于向上转型,a对象会遗失和父类不同的方法,如methods();
简记:A a = New B()是new的子类对象,父类的引用指向它。儿子自己挣的东西,父亲不能访问。父亲给儿子留下的(extends)或者儿子重写父亲的东西,父亲才能访问
答案:
Father sleep

son eat 

son method

抽象类和抽象方法

  • 抽象方法

使用abstract修饰的方法,没有方法体,只有声明。定义的是一种规范,就是告诉子类必须要给抽象方法提供具体的实现

  • 抽象类

包含抽象方法的类就是抽象类,通过abstract方法定义规范,然后要求子类必须定义具体实现。通过抽象类,我们就可以严格限制子类的设计,便子类之间更加实用。

在Java中,没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

抽象类的使用要点

  1. 有抽象方法的类只能定义为抽象类
  2. 抽象类不能直接实例化,即不能用new来实例化抽象类。但是可以参照多态的方式,通过子类对象实例化,这就抽象多态
  3. 抽象类可以包含属性,方法,构造方法。但是构造方法不能用来new实例,只能用来被子类调用
  4. 抽象类只能用来被继承
  5. 抽象方法必须被子类重写
  6. 抽象类的子类:要么重写抽象类中所有的抽象方法,要么是抽象类
abstract class Animal{
    abstract public void shout();//抽象方法
}
class Dog extends Animal{
//子类必须重写父类的抽象方法,要么子类也必须为抽象类,否则编译错误
    public void shout(){
        System.out.println("汪汪汪");
    }
    public void seeDor(){
        System.out.println("看门中.....")
    }

}
//测试抽象类
public class test{
    public static void main(String[],args){
        Dog a=new Dog();
        a.shout();
        a.seeDor();
    }
}

接口


接口用关键字interface修饰

public interface 接口名{......}

类是实现接口,而不是继承接口。用implements来实现

public class wxx implements lwx{
//具体内容......
}//意思是wxx类实现lwx类接口

接口的成员特点

  • 成员变量:只能是常量(系统默认修饰符为public static final)由于接口里面的属性都是默认被final修饰了的,所以能够通过“接口名.属性”来访问属性

 下面这张图里面,Inter是接口,InterImpl是实现接口的类

  • 构造方法:接口没有构造方法,因为接口主要是对行为进行抽象,是没有具体存在,一个类如果没有父类,默认继承自Object类
  • 成员方法:只能是抽象方法(默认修饰符为public absrtact)关于接口中的方法,(JDK8和JDK9中有一些新特性,记得后面来补充)

抽象类和接口的区别

抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象

设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。

  • 成员区别
  1. 抽象类                变量,常量;有构造方法;有抽象方法,也有非抽象方法
  2. 接口                    常量;抽象方法
  • 关系区别 
  1. 类与类               继承,单继承都可以
  2. 类与接口           实现关系  单实现,多实现都可以,还可以在继承一个类的同时实现多个接口
  3. 接口与接口       继承关系    单继承,多继承都可以
public class interImpl extends implements Inter1,Inter2,Inter3{
//具体内容......
}
public interface inter3 extends inter1,inter2{
//具体内容.....
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笃岩_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值