06 面向对象:多态&抽象类&接口&权限修饰符&内部类

Posted fly-book

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06 面向对象:多态&抽象类&接口&权限修饰符&内部类相关的知识,希望对你有一定的参考价值。

多态:

/*
 多态(polymorphic)概述
    * 事物存在的多种形态
 多态前提
    * a:要有继承关系。
    * b:要有方法重写。
    * c:要有父类引用指向子类对象。
* 成员变量
    * 编译看左边(父类),运行看左边(父类)。
* 成员方法
    * 编译看左边(父类),运行看右边(子类)。动态绑定
* 静态方法
    * 编译看左边(父类),运行看左边(父类)。
    * (静态和类相关,算不上重写,所以,访问还是左边的)
    * 只有非静态的成员方法,编译看左边,运行看右边

*/
class Demo_Polymorphic {
    public static void main(String[] args)
    {
        Animal a = new Cat(); // 父类引用指向子类对象
        a.eat(); // 猫吃鱼 // 如果父类没有eat方法就会报错,编译看左边(父类)
        System.out.println(a.num); // 10 成员变量,运行看父类
        a.method(); // Animal static method ,相当于Animal.method()
    }
}
class Animal
{
    int num = 10;
    public void eat(){
        System.out.println("动物吃饭");
    }
    public static void method(){
        System.out.println("Animal static method");
    }
}
class Cat extends Animal
{
    int num = 20;
    public void eat(){
        System.out.println("猫吃鱼");
    }
    public static void method(){
        System.out.println("Cat static method");
    }
}

 

技术分享图片
/*
* A:多态的好处
    * a:提高了代码的维护性(继承保证)
    * b:提高了代码的扩展性(由多态保证)
* B:可以当作形式参数,可以接收任意子类对象
* C:多态的弊端
    * 不能使用子类的特有属性和行为。
*/
class Demo_Polymorphic1 {
    public static void main(String[] args)
    {
        Animal a = new Cat();// 向上转型
        a.eat();
        Cat c = (Cat)a; //向下转型
        c.method();

    //    Animal a2 = new Dog();
        methods(new Dog());
    }
    public static void methods(Animal a){ // 作形式参数
        if (a instanceof Cat)
        {
            Cat c = (Cat)a;
            c.method();
        }
        else if (a instanceof Dog)
        {
            Dog d = (Dog)a;    
            d.method();
        }else{
            a.eat();
        }
    }
}
class Animal
{
    public void eat(){
        System.out.println("动物吃饭");
    }
}
class Cat extends Animal
{
    public void eat(){
        System.out.println("猫吃鱼");
    }
    public void method(){
        System.out.println("猫捉老鼠");
    }

}
class Dog extends Animal
{
    public void eat(){
        System.out.println("狗吃肉");
    }
    public void method(){
        System.out.println("狗看门");
    }
}
多态的好坏

抽象的特点:

/*
抽象类特点
    * a:抽象类和抽象方法必须用abstract关键字修饰
        * abstract class 类名 {}
        * public abstract void eat();
    * b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
    * c:抽象类不能实例化那么,抽象类如何实例化呢?
        * 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    * d:抽象类的子类
        * 要么是抽象类
        * 要么重写抽象类中的所有抽象方法
*
    * 抽象类特点B:抽象类特点
    * a:抽象类和抽象方法必须用abstract关键字修饰
        * abstract class 类名 {}
        * public abstract void eat();
    * b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
    * c:抽象类不能实例化那么,抽象类如何实例化呢?
        * 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    * d:抽象类的子类
        * 要么是抽象类
        * 要么重写抽象类中的所有抽象方法
*/
class Demo_Abstract {
    public static void main(String[] args)
    {
    //    Animal a = new Animal();//错误: Animal是抽象的; 无法实例化
        new Cat().method();
    }
}
abstract class Animal
{
    public abstract void method();
    public void eat(){
        System.out.println("eat");
    }
}
class Cat extends Animal
{
    public void method(){
        System.out.println("捉老鼠");
    }
}


抽象类的成员特点:
* 抽象类的成员特点
    * a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?不能修饰成员

变量
    * b:构造方法:有。
        * 用于子类访问父类数据的初始化。
    * c:成员方法:既可以是抽象的,也可以是非抽象的。
* 抽象类的成员方法特性:
    * a:抽象方法 强制要求子类做的事情。
    * b:非抽象方法 子类继承的事情,提高代码复用性。

一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
    * 可以
    * 这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成
abstract不能和哪些关键字共存
    abstract和static
    被abstract修饰的方法没有方法体
    被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的
    abstract和final
    被abstract修饰的方法强制子类重写
    被final修饰的不让子类重写,所以他俩是矛盾
    abstract和private
    被abstract修饰的是为了让子类看到并强制重写
    被private修饰不让子类访问,所以他俩是矛盾的

abstract class Demo {
    //public static abstract void print();        //错误: 非法的修饰符组合: abstract

和static
    //public final abstract void print();        //错误: 非法的修饰符组合: abstract

和final
    private abstract void print();                //错误: 非法的修饰符组合:

abstract和private
}


接口:

/*
* A:接口概述
    * 从狭义的角度讲就是指java中的interface
    * 从广义的角度讲对外提供规则的都是接口
* B:接口特点
    * a:接口用关键字interface表示    
        * interface 接口名 {}
    * b:类实现接口用implements表示
        * class 类名 implements 接口名 {}
    * c:接口不能实例化
        * 按照多态的方式来实例化。
    * d:接口的子类
        * a:可以是抽象类。但是意义不大。
        * b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
*/
class Demo_Interface {
    public static void main(String[] args)
    {
    //    Inter i = new Inter();//错误: Inter是抽象的; 无法实例化
        Inter i = new A(); // 按照多态的方式实例化
        i.print();

        new Y().print();
    }
}
interface Inter
{
    public abstract void print(); // 接口中的方法都是抽象的
}
class A implements Inter
{
    public void print(){
        System.out.println("a");
    }
}
/*
接口成员特点
    * 成员变量;只能是常量,并且是静态的并公共的。
            * 默认修饰符:public static final
            * 建议:自己手动给出。
    * 构造方法:接口没有构造方法。
    * 成员方法:只能是抽象方法。
            * 默认修饰符:public abstract
            * 建议:自己手动给出。
*/
interface X
{
    public static final int num = 10;
    public abstract void print();

//    public X(){}//接口没有构造方法

//    public void print(){} // 只能是抽象方法

}
class Y implements X
{
    public Y(){
        super();  // 父类object
    }
    public void print(){
        System.out.println(num);
    }

}

class Demo3_Interface {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

/*
* 类与类,类与接口,接口与接口的关系
    * a:类与类:
        * 继承关系,只能单继承,可以多层继承。
    * b:类与接口:
        * 实现关系,可以单实现,也可以多实现。
        * 并且还可以在继承一个类的同时实现多个接口。
    * c:接口与接口:
        * 继承关系,可以单继承,也可以多继承。
*/

interface InterA {
    public abstract void printA();
}

interface InterB {
    public abstract void printB();
}

interface InterC extends InterB,InterA {
}
//class Demo implements InterA,implements InterB {        //这么做不允许是非法的
class Demo extends Object implements InterA,InterB {
    public void printA() {
        System.out.println("printA");
    }

    public void printB() {
        System.out.println("printB");
    }
}

 

class Demo3_Interface {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

/*
* A:类与类,类与接口,接口与接口的关系
    * a:类与类:
        * 继承关系,只能单继承,可以多层继承。
    * b:类与接口:
        * 实现关系,可以单实现,也可以多实现。
        * 并且还可以在继承一个类的同时实现多个接口。
    * c:接口与接口:
        * 继承关系,可以单继承,也可以多继承。
*/

interface InterA {
    public abstract void printA();
}

interface InterB {
    public abstract void printB();
}

interface InterC extends InterB,InterA {
}
//class Demo implements InterA,implements InterB {        //这么做不允许是非法的
class Demo extends Object implements InterA,InterB {
    public void printA() {
        System.out.println("printA");
    }

    public void printB() {
        System.out.println("printB");
    }
}

class Demo3_Interface {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

/*
* A:类与类,类与接口,接口与接口的关系
    * a:类与类:
        * 继承关系,只能单继承,可以多层继承。
    * b:类与接口:
        * 实现关系,可以单实现,也可以多实现。
        * 并且还可以在继承一个类的同时实现多个接口。
    * c:接口与接口:
        * 继承关系,可以单继承,也可以多继承。
*/

interface InterA {
    public abstract void printA();
}

interface InterB {
    public abstract void printB();
}

interface InterC extends InterB,InterA {
}
//class Demo implements InterA,implements InterB {        //这么做不允许是非法的
class Demo extends Object implements InterA,InterB {
    public void printA() {
        System.out.println("printA");
    }

    public void printB() {
        System.out.println("printB");
    }
}

class Demo3_Interface {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

/*
* A:类与类,类与接口,接口与接口的关系
    * a:类与类:
        * 继承关系,只能单继承,可以多层继承。
    * b:类与接口:
        * 实现关系,可以单实现,也可以多实现。
        * 并且还可以在继承一个类的同时实现多个接口。
    * c:接口与接口:
        * 继承关系,可以单继承,也可以多继承。
*/

interface InterA {
    public abstract void printA();
}

interface InterB {
    public abstract void printB();
}

interface InterC extends InterB,InterA {
}
//class Demo implements InterA,implements InterB {        //这么做不允许是非法的
class Demo extends Object implements InterA,InterB {
    public void printA() {
        System.out.println("printA");
    }

    public void printB() {
        System.out.println("printB");
    }
}

抽象类和接口的区别

* 成员区别
    * 抽象类:
        * 成员变量:可以变量,也可以常量
        * 构造方法:有
        * 成员方法:可以抽象,也可以非抽象
    * 接口:
        * 成员变量:只可以常量
        * 成员方法:只可以抽象

* 关系区别
    * 类与类
        * 继承,单继承
    * 类与接口
        * 实现,单实现,多实现
    * 接口与接口
        * 继承,单继承,多继承

* 设计理念区别
    * 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
    * 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。


为什么要有包:
    * 将字节码(.class)进行分类存放
    * 包其实就是文件夹

包的定义及注意事项
* A:定义包的格式
    * package 包名;
    * 多级包用.分开即可
* B:定义包的注意事项
    * A:package语句必须是程序的第一条可执行的代码
    * B:package语句在一个java文件中只能有一个
    * C:如果没有package,默认表示无包名

如何编译运行带包的类:
    * a:javac编译的时候带上-d即可
        * javac -d . HelloWorld.java
    * b:通过java命令执行。
        * java 包名.HellWord
import关键字的概述和使用:
* 为什么要有import
        * 其实就是让有包的类对调用者可见,不用写全类名了
* 导包格式
    * import 包名;
    * 注意:
          这种方式导入是到类的名称。
          虽然可以最后写*,但是不建议。


四种权限修饰符:

  本类           同一个包下(子类和无关类)  不同包下(子类) 不同包下(无关类)
private      Y      
 默认         Y Y    
protected    Y Y Y  
public         Y Y Y Y


类及其组成所使用的常见修饰符:

* A:修饰符:
    * 权限修饰符:private,默认的,protectedpublic
    * 状态修饰符:staticfinal
    * 抽象修饰符:abstract
* B:类:
    * 权限修饰符:默认修饰符,public
    * 状态修饰符:final
    * 抽象修饰符:abstract

    * 用的最多的就是:public

* C:成员变量:
    * 权限修饰符:private,默认的,protectedpublic
    * 状态修饰符:staticfinal

    * 用的最多的就是:private

* D:构造方法:
    * 权限修饰符:private,默认的,protectedpublic

    * 用的最多的就是:public

* E:成员方法:
    * 权限修饰符:private,默认的,protectedpublic
    * 状态修饰符:staticfinal
    * 抽象修饰符:abstract

    * 用的最多的就是:public

* F:除此以外的组合规则:
    * 成员变量:public static final 接口
    * 成员方法:
        * public static
        * public abstract
        * public final



内部类访问特点
    * a:内部类可以直接访问外部类的成员,包括私有。
    * b:外部类要访问内部类的成员,必须创建对象。
    * 外部类名.内部类名 对象名 = 外部类对象.内部类对象;

class Demo_Inner {
    public static void main(String[] args)
    {
        Outer.Inner oi = new Outer().new Inner();
        oi.method();
        // 访问内部类的私有使用
        Outer2 o = new Outer2();
        o.print();
        // 访问静态成员内部类
        Outer3.Inner o3 = new Outer3.Inner();
        o3.method();

        Outer4.Inner.method();
    }
}
class Outer
{
    private int num = 10;
    class Inner
    {
        public void method(){
            System.out.println(num);
        }
    }
}
// 内部类的私有使用
class Outer2
{
    private int num = 10;
    private class Inner
    {
        public void method(){
            System.out.println(num);
        }
    }
    public void print(){
        new Inner().method();
    }
}
/*
静态成员内部类
* 成员内部类被静态修饰后的访问方式是:
    * 外部类名.内部类名 对象名 = 外部类名.内部类对象;
*/
class Outer3
{
    static class Inner
    {
        public void method(){
            System.out.println("static");
        }
    }
}
class Outer4
{
    static class Inner
    {
        public static void method(){
            System.out.println("static");
        }
    }
}


使用已知的变量,在控制台输出30,20,10。
  

 // 内部类之所以能获得外部类的成员,是因为他能获取到外部类的引用 外部类名.this
        class Outer {
            public int num = 10;
            class Inner {
                public int num = 20;
                public void show() {
                    int num = 30;
                    System.out.println(num);
                    System.out.println(this.num);
                    System.out.println(Outer.this.num);
                }
            }
        }
        class InnerClassTest {
            public static void main(String[] args) {
                Outer.Inner oi = new Outer().new Inner();
                oi.show();
            }    
        }

class Demo_InnerClass {
    public static void main(String[] args)
    {
        Outer o = new Outer();
        o.method();
    }
}
// 局部内部类
class Outer
{
    public void method(){
        final int num = 10; //  局部内部类访问局部变量必须用final修饰
        class Inner
        {
            public void print(){
                System.out.println(num);
            }
        }
        new Inner().print();
    }
    /*
    public void Test(){
        new Inner().print();// 错误,局部内部类,只能在其所在的方法中访问
    }
    */
}

/*
    * 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
        因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周

期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部

变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可

以继续使用

        但是jdk1.8,如果在书写代码时候,没有手动添加,系统底层也会默给你final

*/


匿名内部类:

/*
* A:匿名内部类
    * 就是内部类的简化写法。
* B:前提:存在一个类或者接口
    * 这里的类可以是具体类也可以是抽象类。
* C:格式:
        new 类名或者接口名(){
            重写方法;
        }
* D:本质是什么呢?
    * 是一个继承了该类或者实现了该接口的子类匿名对象。
*/
class Demo_InnerClass2 {
    public static void main(String[] args)
    {
        new Outer().method();
    }
}
interface Inner
{
    public abstract void print();
}
class Outer
{
    public void method(){
        new Inner(){
            public void print(){
                System.out.println("Hello World!");
            }
        }.print();
    }
}
// 匿名内部类重写多个方法调用
// 建议匿名类只针对重写一个方法时候使用
interface Inner2
{
    public abstract void print1();
    public abstract void print2();
}
class Outer2
{
    public void method(){
        Inner2 i = new Inner2(){  // 父类引用指向子类对象
            public void print1(){
                System.out.println("print1");
            }
            public void print2(){
                System.out.println("print1");
            }
            /*
            public void print3(){
                System.out.println("print3");
            }
            */
        };
        i.print1();
        i.print2();
    //    i.print3(); // 匿名内部类是不能向下转型的,因为没有自类类名
    }
}

 

class Test_NoNameInnerClass {
    public static void main(String[] args)
    {
        Outer.method().show();
        // 相当于
        Inter i = Outer.method();
        i.show();
    }
}
interface Inter
{
    void show();
}
class Outer
{
    public static Inter method(){
        return new Inter(){
            public void show(){
                System.out.println("Hello World!");
            }
        };
    }
}
/*
Hello World!
*/

 


重写补充:返回值类型是子父类

技术分享图片
/*
重写:子父类出现了一模一样的方法
(注意:返回值类型可以是子父类)
*/
class Demo_FaSonClass {
    public static void main(String[] args)
    {
        
    }
}
class Person
{
    public void print(){
        System.out.println("Hello World!");
    }
}
class Person2 extends Person  
{
    public void print(){
        System.out.println("Hello World!2");
    }
}
class Father
{
    public Person method(){
        return new Person();  //Person与Person2 是子父类
    }
}
class Son extends Father
{
    public Person2 method(){
        return new Person2(); //Person与Person2 是子父类
    }
}
View Code

 































































以上是关于06 面向对象:多态&抽象类&接口&权限修饰符&内部类的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE知识-09(面向对象_多态&抽象类&接口)

2019-05-17 Java学习日记之面向对象_多态&抽象类&接口

面向对象 & 接口 & 抽象类 详解

面向对象的理解 抽象类&接口

面向对象之多态性(接口类)和抽象类

php面向对象 封装继承多态 接口重载抽象类最终类总结