Java学习笔记-基础语法Ⅳ
阅读原文时间:2023年07月08日阅读:2

多态:同一个对象,在不同时刻表现出来的不同形态

例如:

猫 cat = new 猫();

动物 animal = new 猫();

这里的猫在不同时刻表现出来不同的形态,这就是多态

多态的前提和体现:继承/实现方法、方法重写、父类引用指向子类对象

多态访问成员的特点:

  • 成员变量:编译看左边,运行看左边

  • 成员方法:编译看左边,运行看右边

    // Animal类
    public class Animal {
    public int age = 30;
    public void eat(){
    System.out.println("动物吃东西");
    }
    }

    // Cat类
    public class Cat extends Animal{
    public int age = 20;
    public int weight = 10;

    @Override
    public void eat() {
        System.out.println("猫吃东西");
    }
    public void play(){
        System.out.println("猫在玩");
    }

    }

    // 测试类
    public class Demo {
    public static void main(String[] args) {
    Animal cat = new Cat();
    // 对于变量,编译看左边,运行看左边
    System.out.println(cat.age);
    cat.age = 50;
    // 但是如果在测试类中修改了变量值,那么还是会变化的,这个和方法重写又有点不一样
    System.out.println(cat.age);
    // System.out.println(cat.weight);
    // 对于方法,编译看左边,运行看右边,因为重写了
    cat.eat();
    // 报错
    // cat.play();
    }
    }

多态的好处:提高程序的扩展性,定义方法的时候使用父类型作为参数,使用时使用具体子类型的内容

// 动物类
public class Animal {
    public void eat(){
        System.out.println("动物吃东西");
    }
}


// Cat类
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}


// Dog类
public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}


// 操作方法
public class AnimalOperator {
    /*
    public void useAnimal(Cat cat){
        cat.eat();
    }
    public void useAnimal(Dog dog){
        dog.eat();
    }
     */
    public void useAnimal(Animal a){
        a.eat();
    }
}


public class Demo {
    public static void main(String[] args) {
        Cat c = new Cat();
        AnimalOperator ao = new AnimalOperator();
        ao.useAnimal(c);

        Dog d = new Dog();
        ao.useAnimal(d);
    }
}

可以看到,使用多态,在写操作方法时,不用再一个个写,而是直接写父类,然后后面根据具体子类的内容进行调用

多态转型,从父类到了子类,并且可以既使用父类变量和方法,也可以使用子类变量和方法

// 父类
public class Animal {
    public int age = 10;
    public int sex = 20;
    public void eat(){
        System.out.println("动物吃东西");
    }
    public void show(){
        System.out.println("Hello World!");
    }
}


// 子类
public class Cat extends Animal{
    public int age = 30;
    public int name = 40;
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void playGame(){
        System.out.println("猫在玩");
    }
}


// 测试类
public class Demo {
    public static void main(String[] args) {
        Animal a = new Cat();
        System.out.println(a.age);
        System.out.println(a.sex);
        a.eat();
        a.show();

        System.out.println("---------");

        Cat cc = (Cat)a;
        System.out.println(cc.sex);
        System.out.println(cc.age);
        System.out.println(cc.name);
        cc.eat();
        cc.playGame();
        cc.show();
    }
}

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

public void XXX(){System.out.prinln("xxxxx")}

上述方法包含方法声明和方法体

抽象类不能直接创建对象

抽象类的特点:

  • 抽象类和抽象方法必须使用abstract关键字修饰
  • 抽象类中不一定有抽象方法(吃饱了撑的),有抽象方法的一定是抽象类
  • 抽象类不能直接实例化,可以通过子类对象实例化(抽象类多态)
  • 抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类

抽象类可以有构造方法

// 动物类
public abstract class Animal {
    private int age;
    private String name;

    public Animal(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public Animal() {
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void eat();

}


// 猫类
public class Cat extends Animal{
    public Cat(int age, String name) {
        super(age, name);
    }

    public Cat() {
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}


// 测试类
public class Demo {
    public static void main(String[] args) {
        Animal cat1 = new Cat();
        cat1.setAge(18);
        cat1.setName("小猫");
        cat1.eat();

        Animal cat2 = new Cat(17, "小小猫");
        cat2.eat();
    }
}

抽象类用自己的话小结:其他的和正常类没什么不同(主要是与接口对比),但是一般来说要有抽象方法

接口:一种公共的规范标准,只要符合规范标准,就都可以用。Java的接口体现在对行为的抽象

public interface 接口名{}

public class 类名 implements 接口名 {}

接口实例化:抽象类多态、接口多态,前提是有继承或者实现关系,有方法重写,且有父(类/接口)引用指向(子/接口)类对象

// 接口
public interface Jumpping {
    public abstract void jump();
}


// 实现
public class Cat implements Jumpping{
    @Override
    public void jump() {
        System.out.println("猫跳高");
    }
}


// 测试类
public class Demo1 {
    public static void main(String[] args) {
        Jumpping j = new Cat();
        j.jump();
    }
}


public abstract class Dog implements Jumpping{
}


public class DogDemo extends Dog{
    @Override
    public void jump() {
        System.out.println("狗跳高");
    }
}


public class Demo2 {
    public static void main(String[] args) {
        Jumpping j = new DogDemo();
        j.jump();
    }
}

接口的成员特点:

  • 成员变量:只能是常量,默认修饰符:public static final
  • 构造方法:接口没有构造方法,接口主要对行为进行抽象,其子类默认继承Object类
  • 成员方法:只能是抽象方法,默认修饰符:public abstract

下面将使用一个继承抽象类并且实现接口

// 接口
public interface Inter {
    void jumping();
    // 验证调用,写在接口中的变量可以调用,但是不可以修改
    int sex = 1;
}


// 抽象类
public abstract class Animal {
    private String name;
    private int age;
    // 验证调用
    public static int height = 10;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public abstract void eat();
}


// 猫类
public class Cat extends Animal implements Inter{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    @Override
    public void jumping() {
        System.out.println("猫跳高");
    }

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }
}


// 测试类
public class Demo {
    public static void main(String[] args) {
        Cat cat1 = new Cat();
        cat1.setAge(18);
        cat1.setName("加菲");
        cat1.eat();
        cat1.jumping();

        Cat cat2 = new Cat("布偶",16);
        System.out.println(cat2.getAge()+" "+cat2.getName());
        System.out.println(cat2.sex);
        System.out.println(cat2.height);
    }
}

类和接口的关系:

  • 类和类:继承关系,只能单继承,但不能多继承
  • 类和接口:类实现接口,可以单实现,也可以多实现
  • 接口和接口:可以单继承,也可以多继承

抽象类和接口的区别:

  • 成员区别:接口只有常量和抽象方法,抽象类几乎没什么限制
  • 关系区别:接口可以实现多继承
  • 设计理念:接口主要是行为上,抽象类主要是对象抽象,包括属性、行为

// 接口
public interface English {
    void speak_english();
}


// 人的抽象类
public abstract class Person {
    private int age;
    private String name;

    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public abstract void eat();
}


// 教练的抽象类
public abstract class Coach extends Person{
    public abstract void teach();

    public Coach() {
    }

    public Coach(int age, String name) {
        super(age, name);
    }
}


// 运动员抽象类
public abstract class Athlete extends Person{
    public abstract void study();
    public Athlete() {
    }

    public Athlete(int age, String name) {
        super(age, name);
    }
}


// 乒乓教练具体类
public class PinPonCoach extends Coach implements English{
    public PinPonCoach() {
    }

    public PinPonCoach(int age, String name) {
        super(age, name);
    }

    @Override
    public void teach() {
        System.out.println("乒乓教练教评判");
    }

    @Override
    public void eat() {
        System.out.println("乒乓教练吃肉");
    }

    @Override
    public void speak_english() {
        System.out.println("乒乓教练学英语");
    }
}


// 篮球运动员具体类
public class BasketBallAthlete extends Athlete {
    public BasketBallAthlete() {
    }

    public BasketBallAthlete(int age, String name) {
        super(age, name);
    }

    @Override
    public void eat() {
        System.out.println("篮球运动员吃饭");
    }

    @Override
    public void study() {
        System.out.println("篮球运动员学篮球");
    }
}


// 测试类
public class Demo {
    public static void main(String[] args) {
        PinPonCoach pc = new PinPonCoach();
        pc.setAge(18);
        pc.setName("lll");
        System.out.println(pc.getAge()+" "+pc.getName());
        pc.speak_english();
        pc.eat();
        pc.teach();
        System.out.println("----------");
        BasketBallAthlete bba = new BasketBallAthlete(18,"kkk");
        bba.eat();
        bba.study();
        System.out.println(bba.getAge()+" "+bba.getName());
    }
}

接口方法调用(抽象类)

// 接口
public interface Jumping {
    void jump();
}


// 操作类
public class JumpOperator {
    public void jump(Jumping j){
        j.jump();
    }
    public Jumping getJump(){
        Jumping j = new Cat();
        return j;
    }
}


// 用于接口实例化的猫类
public class Cat implements Jumping{
    @Override
    public void jump() {
        System.out.println("猫跳高");
    }
}


// 测试类
public class Demo {
    public static void main(String[] args) {
        JumpOperator jo = new JumpOperator();
        Jumping j = new Cat();
        jo.jump(j);

        Jumping jump = jo.getJump();
        jump.jump();
    }
}

内部类:在类中定义一个类

内部类可以直接访问外部类的成员,包括私有,外部类若想访问内部类的成员,必须创建对象

在自己写代码的过程中,还遇到了一点问题,也记录下来

public class Outer {
    private static int num = 10;

    public static class Inner{
        public void show(){
            System.out.println("Hello");
            System.out.println(num);
        }
    }

    public void method(){
        Inner i = new Inner();
        i.show();
    }
    public static void main(String[] args) {
        Inner i = new Inner();
        i.show();
    }
    public int x = 1;
    public int y = x+2;
//    x = x+3;
    public int age = 10+x;
    Inner i = new Inner();
    // 不能直接实例话后调用
//    i.show();
}

想在中直接创建另一个类的对象,然后调用方法,但是报错了,并且这时候试了下对变量进行运算也报错

查了下资料,发现类中只能出现5中内容:

属性、方法、构造方法、块以及内部类

但是初始化默认值时,可以进行一些运算操作(现在不是很懂这样的逻辑,先记录下来)

成员内部类,可以用private修饰,然后通过方法调用,这样外部使用的时候就看不到类中细节

成员内部类

public class Outer {
    private int age = 20;
    private class Inner{
        public void show(){
            System.out.println(age);
        }
    }
    public void method(){
        Inner i = new Inner();
        System.out.println(age);

    }
}


public class Demo {
    public static void main(String[] args) {
//        Outer.Inner oi = new Outer().new Inner();
//        oi.show();
        Outer o = new Outer();
        o.method();
    }
}

局部变量前面不加修饰符

方法内部类

public class Outer {
    private int age = 18;
    public void method(){
        // 局部变量不加修饰符
        class Inner{
            public void show() {
                String name = "Hello";
                System.out.println(age);
            }
        }
        Inner i = new Inner();
        i.show();
    }
}


public class Demo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

匿名内部类

public class Outer {
    public void show1() {
        /*
        new Inter(){
            @Override
            public void show() {
                super.show();
//                System.out.println("World");
            }
        }.show();

         */
        Inter i = new Inter(){
            @Override
            public void show() {
                super.show();
            }
        };
        i.show();
    }
}


public class Inter {
    public void show(){
        System.out.println("Hello");
    }
}


public class Demo {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.show1();
    }
}

匿名内部类在实际开发中的应用:

// 接口
public interface Inter {
    void jump();
}


// 方法
public class InterImplements {
    public void show(Inter i){
        i.jump();
    }
}


// 测试
public class Demo {
    public static void main(String[] args) {
        InterImplements ii = new InterImplements();
        ii.show(new Inter() {
            @Override
            public void jump() {
                System.out.println("狗跳高");
            }
        });
    }
}

到此,Java学习中的基本编程思想告一段落,下面将是常用API