当前位置: 移动技术网 > IT编程>开发语言>Java > 多态,内部类

多态,内部类

2020年07月17日  | 移动技术网IT编程  | 我要评论

一。接口作为方法参数, 接口作为返回值:
具体使用的都是接口的实现类对象

1.创建接口
public interface Interface1 {
    void method1();
    void method2();
}
2.创建实现类
public class InterfaceImpl implements  Interface1{
    @Override
    public void method1() {
        System.out.println("实现类重写方法1");
    }

    @Override
    public void method2() {
        System.out.println("实现类重写方法2");
    }
}
3. 接口类型作为方法参数,返回值为接口类型
public class DemoIt {
    //接口类型返回值的方法
    public Interface1 it(Interface1 a){
        //此处等于默认有 Interface a=new InterfaceImpl();
        // a 调用的是哪个方法, 具体看传入的对象是哪个实现类
        a.method1();
        a.method2();
        System.out.println("结束");
        /*相当于创建了一个接口的实现类对象, 向上造型为接口类型
        Interface a=new InterfaceImpl();
        接口类型的对象返回return a;*/
        return a;//等于return new InterfaceImpl();
    }
}
4.主函数调用

public class Main {
    public static void main(String [] ages){
        DemoIt demo=new DemoIt();
        //接口无法创造对象,所以用实现类创造对象
        InterfaceImpl a=new InterfaceImpl();
        //实现类对象作为参数给It方法中的接口类型参数做参数
        demo.it(a);

        InterfaceImpl a2=new InterfaceImpl();
        //调用方法并且接收返回值时,由于 xx.it(xx)返回值是Interface类型
        Interface1 re=demo.it(a2);
    }
}

二。多态

1.父类
public class Fu {
    int age = 10;
    int num = 100;

    public void m1() {
        System.out.println("Fu m1方法");
    }

    public void m2() {
        System.out.println("Fu m2方法");
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
2.子类
public class Zi extends Fu {
    // 和父类中同名的成员变量
    int age = 20;
    // 和父类中不同的成员变量 - 子类自己单独声明的
    int score = 150;
    // 额外继承了父类中的num变量

    // 重写父类中的m1方法
    public void m1() {
        System.out.println("Zi m1方法");
    }
    // 继承了父类的m2方法

    // 子类自己的方法 m3
    public void m3() {
        System.out.println("Zi m3方法");
    }

    @Override
    public int getAge() {
        return age;
    }

}
3.父类型引用 指向 子类型对象
 Fu f = new Zi();
 // 无关类 不叫 向上造型, 写法错误
//        Fu f1 = new Self();
/*
以下两种不叫多态
        Fu f1 = new Fu();
        Zi zi = new Zi();
*/
4.多态表现方面1: 
    成员变量的调用, 子父类中拥有相同的成员变量并且都有一对get/set方法
    如果通过引用直接调用成员变量 f.age, 看引用变量f左边类型来调用
    通过方法调用成员变量f.getAge(), 看引用变量右边类型来调用
    public class Main1 {
    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.age); // 10

        // 子类中重写了getAge()方法, 得到20
        // 子类中没有重写getAge()方法, 得到10
        System.out.println(f.getAge()); // 20

        System.out.println(f.num);
        // Fu类中没有声明score变量, 不能直接调用
//        System.out.println(f.score);
        // int a = (int)3.14;   double d = 3;
        // 向下转换类型
        Zi zi = (Zi) f;
        System.out.println(zi.score);

    }
}
5. 多态的表现方面2: 成员方法的调用
 最终调用的是哪个方法:优先调用子类重写过的,子类中如果没有重写, 
 就调用父类的方法
 public class Main2 {
    public static void main(String[] args) {
        Fu f = new Zi();
        f.m1();
        // m3没有在Fu中声明, 所以不能直接调用
//        f.m3();
        // 如果想用子类自己的方法, 需要强制转换
        Zi zi = (Zi) f;
        zi.m3();
    }
}

②多态: Animal a1 = new Cat();
Animal a2 = new Dog();

1.抽象父类,抽象方法
public abstract  class Animal {
    
    public  abstract void eat();
}
2.子类
  public class Cat extends Animal {
     @Override
     public void eat() {
         System.out.println("吃鱼");
     }
     public void catchMouse(){
         System.out.println("抓老鼠");
     }
 }
 public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("吃骨头");
    }
    public void watchHouse(){
        System.out.println("看门");
    }
}
3。多态主要用处是Animal作为参数,可以传递多种类型的对象,以Animal抽象类为返回值的那个方法可以返回多种不同种类的对象
public class Test {
    public static void main(String [] ages){
        //向上造型:父类型引用指向子类型对象
        Animal m1=new Cat();
       // m1.eat();
        Animal m2=new Dog();
       // m2.eat();
       /*
        Cat c=new Cat();
        Dog d=new Dog();
        c.catchMouse();
        d.watchHouse();
        */
        //showCatEat(c);
        //showDogEat(d);
        showAnimalEat(m1);
        showAnimalEat(m2);
    }
    public static Animal salepet(){//以Animal抽象类为返回值,这个方法可以返回多种不同
        return null;
    }
      //Animal作为参数,可以传递多种类型的对象
    public static void showAnimalEat(Animal a){
        if(a instanceof Cat){//instanceof用来判断a是否是new出的Cat
            Cat cat=(Cat) a;
            cat.catchMouse();
        }
        else if( a instanceof Dog){
            Dog dog=(Dog) a;//向下转型
            dog.watchHouse();
        }
        a.eat();
    }
}

三。内部类: 类中写个类
种类: 成员内部类,静态内部类,局部内部类[匿名内部类]
1.成员内部类:权限 public,protected,(default),private
使用:
内部类中, 可以随意使用外部类成员
外部类中, 使用内部类成员时需要创建内部类对象
无关类中, 使用内部类成员
1.间接调用, 在外部类方法中调用内部类方法
main方法中, 调用外部类方法
2.直接调用, 需要创建内部类对象
外部类.内部类 a = new 外部类().new 内部类();
内部类和外部类有同名成员变量
外部类的成员变量: 外部类.this.变量
内部类的成员变量: this.变量

// 外部类
public class Body {
    public void walk() {
        System.out.println("身体在行走");
        // 外部类中, 直接创建内部类对象
        Heart heart = new Heart();
        heart.beat();
        // 外部类中使用内部类成员变量, 需要内部类对象
        System.out.println(heart.num);
        System.out.println(a); // 外部类的a
    }
    private int a = 10;
    // 成员内部类: 成分和外部类一样
    public class Heart {
        int num;
        int a = 20;
        public void beat() {
            int a = 30;
            // 内部类中可以直接使用外部类成员
            System.out.println("心脏跳动" + a++);
            // 内部类的成员a
            System.out.println(this.a);
            // 外部类的成员变量a
            System.out.println(Body.this.a);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 在无关类中 使用Body的内部类Heart
        Body body = new Body();
        // 间接调用内部类
        body.walk();

        // 直接调用内部类, 通过外部类对象创建内部类对象
        Body.Heart heart = body.new Heart();//与//Body.Heart heart = new Body().new Heart();相同
        heart.beat();
    }
}

2.局部变量a:
局部内部类中使用局部内部变量必须为final

public class Outer {
    private int b = 20;
    public void m1() {
        // 和局部内部类同方法的局部变量 a
        /*final */int a = 10;
        class Inner {
            public void innerM1() {
                int c = 0;
                System.out.println("局部内部类m1" + a);
                System.out.println("成员变量: " + b);
            }
        }
        Inner i = new Inner();
        i.innerM1();
      //a ++; final 不可变
        b ++;
    }

}

3.局部内部类: 在方法内部定义类, 只在方法中有效
在局部内部类中, 使用局部变量, 必须是final的
JDK8 后, 局部变量事实上没有发生改变, 那么final可以省略
一次性的类, 只能用一次
不能使用权限修饰符
局部内部类, 需要类只使用一次, 优化 -> 匿名内部类

public interface MyInterfaceA {
    void methodAbs1();
    void methodAbs2();
}

// 只想用一次, 只想在Outer类中的m1方法中使用
public class MyInterfaceImpl implements MyInterfaceA {
    @Override
    public void methodAbs1() {
        System.out.println("方法1");
    }

    @Override
    public void methodAbs2() {
        System.out.println("方法2");
    }
}

public class Outer {
    public void m1() {
        class InnerImpl implements MyInterfaceA {
            @Override
            public void methodAbs1() {
                System.out.println("内部类实现1");
            }
            @Override
            public void methodAbs2() {
                System.out.println("内部类实现2");
            }
        }

        // 使用接口的方法, 创建接口的实现类
        InnerImpl impl = new InnerImpl();
        impl.methodAbs1();
        impl.methodAbs2();
    }
}

4.匿名内部类: 继承抽象类或实现接口
语法: new 接口/抽象类() {
int a;
// 实现的所有抽象方法
}
匿名内部类, 只能用一次, new一个对象
匿名对象, 只能使用一次, 只能调用一次方法
注意: 匿名内部类 和 匿名对象 不是一回事 ! ! !

public interface MyInterfaceA {
    void methodAbs1();
    void methodAbs2();
}

public class Outer {
    public static void main(String[] args) {
        // 匿名内部类本质: 实现接口或者继承抽象类
        /*
            new MyInterfaceA(){..}
            new: 创建MyInterfaceA 的实现类对象
            MyInterfaceA: 想要实现的接口, 抽象类
            {..}: 真正的类, 没有名字
            弊端: 只能用一次, 只能创建一次对象
         */
         MyInterfaceA impl = new MyInterfaceA() {
             int a = 10;
            @Override
            public void methodAbs1() {
                System.out.println("内部类实现1" + a++);
            }
            @Override
            public void methodAbs2() {
                System.out.println("内部类实现2");
            }
        };
        impl.methodAbs1();
        impl.methodAbs2();

        new MyInterfaceA() {
            int a = 10;
            @Override
            public void methodAbs1() {
                System.out.println("内部类实现1" + a++);
            }
            @Override
            public void methodAbs2() {
                System.out.println("内部类实现2");
            }
        }.methodAbs1();
        // 匿名对象, 只能调用一次方法
        new Outer().getClass();
        new Outer().hashCode();
    }
}
  1. 静态内部类: 对比 成员内部类 => 静态方法 和 成员方法
public class Outer {

    // 成员方法
    public void m1() {
        new Inner();
        new InnerField();
    }
    // 静态方法
    public static void m2() {
        new Inner();
//        new InnerField();
    }
    // 成员内部类
    public class InnerField {

    }
    // 外部类的成员变量
    int a = 10;
    // 外部类的静态成员变量
    static int b = 20;
    // 静态内部类, 属于类的
    public static class Inner {
        public void m3() {
            // 不能使用非静态成员
//            System.out.println(a);
            System.out.println(b);
        }
    }
}

import com.zzxx.demo8.Outer.Inner;

public class Main {
    public static void main(String[] args) {
        // 成员内部类创建对象, 需要外部类对象
        Outer.InnerField inner1 = new Outer().new InnerField();

        // 静态内部类创建对象
        Outer.Inner inner2 = new Outer.Inner();

        // 简化 -> 需要import
        Inner inner3 = new Outer.Inner();

    }
}

本文地址:https://blog.csdn.net/LDRaaa/article/details/107370083

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网