javase复习day15_抽象类,接口,内部类

抽象类,抽象方法

抽象方法:

定义格式

注意事项:

构造方法的作用:

当创建子类对象时给属性赋值。

public abstract class Person {
    //添加属性
    private String name;
    private int age;

    //设置构造函数用于为子类的属性添加数据
    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //get set用于给子类操作属性

    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 work();
}
package Demo.Demo1;

public class student extends Person{
    public student() {
    }

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

    @Override
    public void work() {
        System.out.println("学生的工作是学生");
    }
}
package Demo.Demo1;

public class Test {
    public static void main(String[] args) {
        student s = new student("zhangsan",20);
        s.work();
        System.out.println(s.getName());
    }
}

抽象类练习一:

package Demo.Demo2;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

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

    public abstract void eat();
    public void drink(){
        System.out.println("喝水");
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Animal{name = " + name + ", age = " + age + "}";
    }
}
package Demo.Demo2;

public class frog extends Animal{
    public frog() {
    }

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

    @Override
    public void eat() {
        System.out.println("吃虫子");
    }
}
package Demo.Demo2;

public class Dog extends Animal{
    public Dog() {
    }

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

    @Override
    public void eat() {
        System.out.println("吃骨头");
    }
}
package Demo.Demo2;

public class Sheep extends Animal{
    public Sheep() {
    }

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

    @Override
    public void eat() {
        System.out.println("吃草");
    }
}
package Demo.Demo2;

public class Test {
    public static void main(String[] args) {
        frog f = new frog("小黄",1);
        System.out.println(f.getName()+", "+f.getAge());
        f.eat();
        f.drink();
    }
}

抽象类的总结:

接口

为什么有接口

接口的理解:

接口不是一种事物他是对行为的抽象是一种规则。

接口的定义与使用

接口练习一:

package Demo.Demo3;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

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

    public abstract void eat();


    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Animal{name = " + name + ", age = " + age + "}";
    }
}
package Demo.Demo3;

public class Dog extends Animal implements swimming {
    public Dog() {
    }

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

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

    @Override
    public void swim() {
        System.out.println("狗在游泳");
    }
}
//兔子不会游泳没有连接接口
package Demo.Demo3;

public class rabit extends Animal {
    public rabit() {
    }

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

    @Override
    public void eat() {
        System.out.println("吃草");
    }
}
package Demo.Demo3;

public class frog extends Animal implements swimming{
    public frog() {
    }

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

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

    @Override
    public void swim() {
        System.out.println("青蛙在游泳");
    }
}
package Demo.Demo3;

public class Test {
    public static void main(String[] args) {
        frog f = new frog("小黄",1);
        System.out.println(f.getName()+", "+f.getAge());
        f.eat();
        f.swim();
    }
}

接口中成员的特点

接口和类之间的关系

接口练习一(Demo5)


package Demo.Demo5;

//将人写为抽象的,用于拒绝外界创建该对象
public abstract class  Person {
    private String name;
    private int 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 Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
//运动员类
package Demo.Demo5;

public abstract class jock extends Person {
    public jock() {
    }

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

    //运动员
    //打球的抽象方法
    public abstract void work();

}
package Demo.Demo5;

public abstract class instructor extends Person{
    public instructor() {
    }

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

    //教练
    public abstract void techer();
}
//说英语的接口
public interface english {
    public abstract void lean();
}
//篮球教练
package Demo.Demo5;

public class basketball_ins extends instructor{
    public basketball_ins() {
    }

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

    @Override
    public void techer() {
        System.out.println("篮球教练教篮球");
    }
}
//篮球运动员
package Demo.Demo5;

public class basketball_player extends jock{
    public basketball_player() {
    }

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

    @Override
    public void work() {
        System.out.println("篮球运动员打篮球");
    }
}
//乒乓球教练
package Demo.Demo5;

public class table_tennis_ins extends instructor implements english{
    public table_tennis_ins() {
    }

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

    @Override
    public void techer() {
        System.out.println("乒乓球教练教篮球");
    }

    @Override
    public void lean() {
        System.out.println("乒乓球教练学英语");
    }
}
//乒乓球运动员
package Demo.Demo5;

public class table_tennis_player extends jock implements english{
    public table_tennis_player() {
    }

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

    @Override
    public void lean() {
        System.out.println("乒乓球运动员学英语");
    }

    @Override
    public void work() {
        System.out.println("乒乓球运动员打乒乓球");
    }
}
package Demo.Demo5;

public class Test {
    public static void main(String[] args) {
        table_tennis_player t = new table_tennis_player("wdwd",20);
        t.lean();
        t.work();
        System.out.println(t.getName()+","+t.getAge());
        System.out.println("===================================");
        basketball_ins b = new basketball_ins("ww",30);
        b.techer();
        System.out.println(b.getName()+","+b.getAge());
    }
}

JDK8开始接口中新增的方法

jdk7之前的问题:只要接口发生变化则实现类也必须进行更改否则就会报错。

有方法体的接口为了接口升级时有兼容性所采取的,接口修改后不需要立马修改,等以后用到哪个规则在进行重写。

JDK8后接口新增的方法

package Demo.Demo6;

public interface inxertA {
    void show1();

    default void show2(){
        System.out.println("接口中的默认方法");
    }
    public default void show3(){
        System.out.println("inxertA中的默认方法");
    }
}
//接口的重名默认方法
package Demo.Demo6;

public interface inxertB {
    public default void show3(){
        System.out.println("inxertB中的默认方法");
    }
}
package Demo.Demo6;

public class InImpl implements inxertA,inxertB{
    @Override
    public void show1() {
        System.out.println("接口中的抽象方法重写");
    }
    //两个接口中的同名默认方法必须要重新写


    @Override
    public void show3() {
        System.out.println("同名默认方法必须要重新写");
    }

    @Override
    public void show2() {
        System.out.println("默认方法重写");
    }
}
package Demo.Demo6;

public class Test {
    public static void main(String[] args) {
        InImpl ii = new InImpl();
        ii.show1();
        ii.show2();
        ii.show3();
    }
}

package Demo.Demo7;

public interface interfice {
    //设一个静态方法
    public static void show(){
        System.out.println("接口中的静态方法,无法被重写");
    }
    //抽象方法
    public abstract void demo();
}
package Demo.Demo7;

public class interImpl implements interfice{
    @Override
    public void demo() {
        System.out.println("抽象方法重写");
    }

    //写一个静态方法(只是和接口中的静态方法刚好重名,不是重写),只有虚方法表中的才能重写,静态方法不在虚方法表。
    public static void show(){
        System.out.println("只是和接口中的静态方法刚好重名,不是重写");
    }
}
package Demo.Demo7;

public class Test {
    public static void main(String[] args) {
        interfice.show();

        interImpl.show();

        interImpl ii = new interImpl();
        ii.demo();
    }
}

JDK9以后得新增的方法

package Demo.Demo8;

public interface interA {
    public default void show1(){
        System.out.println("show1方法开始执行");
        show3();
    }
    public default void show2(){
        System.out.println("show2方法开始执行");
        show3();
    }
    public static void show5(){
        System.out.println("show5静态方法开始执行");
        show4();
    }
    //普通的私有方法,给默认方法服务
    private void show3(){
        System.out.println("记录运行中的各种细节");
    }

    //静态的私有方法,给静态方法服务
    private static void show4(){
        System.out.println("记录运行中的各种细节");
    }

}

新增方法总结:

接口的应用

设计模式

适配器设计模式

内部类

什么是内部类

内部类的应用场景,小结

成员内部类

内部类的分类

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

前三个了解即可,匿名内部类着重掌握。

成员内部类的书写要求

创建成员内部类的对象

package Demo.Demo10;

public class Outer {
    String name;
    //如何在私有下获取内部类的对象
    private  class Inner{

    }
    // 创建一个方法用于返回内部类的对象
    public Inner getInstance(){
        return new Inner();
    }
}
package Demo.Demo10;

public class Test {
    public static void main(String[] args) {
        //创建内部类的对象
//        Outer.Inner i = new Outer(). new Inner();
        //内部类私有下获取对象
        Outer o = new Outer();
        //因为Inner为私有所以Outer.Inner会报错
//        Outer.Inner instance = o.getInstance();
        //解决方案
        //1.使用Inner的父类去接收(即多态)
        Object instance = o.getInstance();
        //2.不使用对象接受而直接使用对象(链式编程)
        System.out.println(o.getInstance());

    }

}

成员内部类练习一:

package Test.Test1;

public class Outer {
    private int a = 10;
    class Inner{
       private int a = 20;
       public void show(){
           int a = 30;
            //获取了外部类对象的地址值
           System.out.println(Outer.this.a);//10
           System.out.println(this.a);//20
           System.out.println(a);//30
       }
    }
}
package Test.Test1;

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

有内部类的内存图解释

内部类的内存图

内部类和外部类在内存中为独立的字节码文件。

成员内部类小结

静态内部类

package Demo.Demo11;

public class Outer {
//    int a = 10;
//    static int b = 20;

    static  class Inner{
        public void show1(){
            System.out.println("非静态方法被调用");
//            //要调用非静态的属性就要先创建对象
//            Outer o = new Outer();
//            System.out.println(o.a);
//            System.out.println(b);
        }
        public static void show2(){
            System.out.println("静态方法被调用");
//            //要调用非静态的属性就要先创建对象
//            Outer o = new Outer();
//            System.out.println(o.a);
//            System.out.println(b);
        }
    }
}
package Demo.Demo11;

public class Test {
    public static void main(String[] args) {
        //调用静态内部类的非静态方法
        Outer.Inner inner = new Outer.Inner();
        inner.show1();
        //调用静态内部类的静态方法
        //不推荐
//        inner.show2();
        //推荐
        Outer.Inner.show2();

    }
}

静态内部类总结

局部内部类

package Demo.Demo12;

public class Outer {
    int a = 10;
    public void show(){
        int b = 20;
        //定义局部内部类
        class Inner{
            int c = 30;
            public void show2(){
                System.out.println(a);
                System.out.println(b);
                System.out.println("局部内部类的非静态方法");
            }
            public static void show3(){
                System.out.println("局部内部类的静态方法");
            }
        }
        //在方法中访问内部类
        Inner i = new Inner();
        System.out.println(i.c);
        i.show2();
        Inner.show3();
    }
}
package Demo.Demo12;

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

匿名内部类

package Demo.Demo13;

public abstract class Swim {
    public abstract void swim();
}
package Demo.Demo13;

public  class Animal {
    public void eat(){
        System.out.println("继承类中的父类");
    }
}
package Demo.Demo13;

public class Test {
    public static void main(String[] args) {
        new Swim(){
            @Override
            public void swim() {
                System.out.println("匿名内部类的重写");
            }
        };
        new Animal(){
            @Override
            public void eat() {
                System.out.println("重写继承类的方法");
            }
        };
        //应用场景,直接在方法中写匿名内部类,将其赋值个静态方法(赋值的对象为匿名
        // 内部类所创建的Animal的子类的对象)
        method(
                new Animal(){
                    @Override
                    public void eat() {
                        System.out.println("重写后的被匿名内部类调用的方法");
                    }
                }
        );

    }

    //写一个静态方法来调用父类的对象
    public static void method(Animal a){
        a.eat();
    }

}
public class Test2 {
    public static void main(String[] args) {
        //将匿名内部类赋值给一个Swim对象
       Swim s = new Swim(){
            @Override
            public void swim() {
                System.out.println("重写后的游泳方法");
            }
        };
       s.swim();

       //将匿名内部类看做一个对象,直接调用方法
        new Swim(){
            @Override
            public void swim() {
                System.out.println("重写后的游泳方法2");
            }
        }.swim();
    }
}
//运行结果
重写后的游泳方法
重写后的游泳方法2

匿名内部类总结

课后练习题

第一题

第一题:

需求:

分析以下需求用代码实现:

  1. 定义形状类:

    功能:求面积,求周长

  2. 定义圆形类Round:

    属性:半径,圆周率

    功能:求面积,求周长

  3. 定义长方形类Rectangle:

    属性:长和宽

    功能:求面积,求周长

  4. 定义测试类:

    分别创建圆形和长方形对象,为相应的属性赋值

    分别调用求面积和求周长的方法

答案

设置接口定义周长和面积两个方法

package Work.Work1;

public interface shape {
    //设置面积和周长两种方法
    //周长
    public double circumference();
    //面积
    public double area();

}

圆的实现类实现了shape接口中的两个方法

package Work.Work1;

public class Round implements shape {
    private double r;
    private static final double pr = 3.1415926;


    public Round() {
    }

    public Round(double r) {
        this.r = r;
    }

    /**
     * 获取
     * @return r
     */
    public double getR() {
        return r;
    }

    /**
     * 设置
     * @param r
     */
    public void setR(double r) {
        this.r = r;
    }

    public String toString() {
        return "Round{r = " + r + ", pr = " + pr + "}";
    }

    //周长的方法
    @Override
    public double circumference() {
        double lenght = 2*pr*r;
        return lenght;
    }

    //获取面积的方法
    @Override
    public double area() {
        double area = pr*r*r;
        return area;
    }
}

长方形的实现类

package Work.Work1;

public class Rectangle implements shape {
    private double longht;
    private double wide;


    public Rectangle() {
    }

    public Rectangle(double longht, double wide) {
        this.longht = longht;
        this.wide = wide;
    }

    /**
     * 获取
     * @return longht
     */
    public double getLonght() {
        return longht;
    }

    /**
     * 设置
     * @param longht
     */
    public void setLonght(double longht) {
        this.longht = longht;
    }

    /**
     * 获取
     * @return wide
     */
    public double getWide() {
        return wide;
    }

    /**
     * 设置
     * @param wide
     */
    public void setWide(double wide) {
        this.wide = wide;
    }

    public String toString() {
        return "Rectangle{longht = " + longht + ", wide = " + wide + "}";
    }

    //周长的方法
    @Override
    public double circumference() {
        return (longht+wide)*2;
    }

    //获取面积的方法
    @Override
    public double area() {
        return longht*wide;
    }
}

Test测试类,用以测试代码是否正确

package Work.Work1;

public class Test {
    public static void main(String[] args) {
        Round r = new Round(3);
        System.out.println("圆的周长为"+r.circumference());
        System.out.println("圆的面积为"+r.area());

        Rectangle re = new Rectangle(3,4);
        System.out.println("长方形的周长为"+re.circumference());
        System.out.println("长方形的面积为"+re.area());
    }
}

第二题

第二题:

需求:

  1. 定义手机类

行为:打电话,发短信

  1. 定义接口IPlay

行为:玩游戏

  1. 定义旧手机类继承手机类

行为:继承父类的行为

  1. 定义新手机继承手机类实现IPlay接口

    行为:继承父类的行为,重写玩游戏方法

  2. 定义测试类

在测试类中定义一个 用手机的方法,要求该方法既能接收老手机对象,也能接收新手机对象

在该方法内部调用打电话,发短信以及新手机特有的玩游戏方法

定义一个Phone的抽象类,用于存储方法

package Work.Work2;

public abstract class Phone  {
    //定义手机抽象类
    abstract void Call();
    abstract void Texting();
}

定义Iplay接口

package Work.Work2;

//定义接口
public  interface IPlay {
    abstract void playgame();
}

两个实现类

package Work.Work2;

public class OldPhone extends Phone{
    @Override
    void Call() {
        System.out.println("旧手机在打电话");
    }

    @Override
    void Texting() {
        System.out.println("旧手机在发消息");
    }

}
package Work.Work2;

public class NewPhone extends Phone implements IPlay{
    @Override
    public void playgame() {
        System.out.println("新手机在玩游戏");
    }

    @Override
    void Call() {
        System.out.println("新手机在打电话");
    }

    @Override
    void Texting() {
        System.out.println("新手机在发消息");
    }
}

测试类(重要,第一时间没做出来

package Work.Work2;

public class Test {
    public static void main(String[] args) {
        OldPhone op = new OldPhone();
        NewPhone np = new NewPhone();
        Test t = new Test();
        t.use(op);
        t.use(np);

    }
    //创建一个方法用于实现要求
    public  void use(Phone phone){
        phone.Call();
        phone.Texting();
//        phone.playgame();
        //判断是否为Iplay的实例,是则执行
        if (phone instanceof IPlay){
            ((IPlay) phone).playgame();
        }
    }
}

第三题

第三题:

需求:

  1. 接口IPlay中有一个方法playGame(),在测试类中如何调用该方法?

要求1.创建子类实现接口的方式实现 要求2:用匿名内部类实现

  1. 一个抽象类Fun中有一个抽象方法 fun() , 在测试类中如何调用该方法?

要求1.创建子类继承抽象类的方式实现 要求2:用匿名内部类实现

答案

一小问:

package Work.Work3;

public interface Iplay {
    void playGame();
}
package Work.Work3;

public class IplayImpl implements Iplay{
    @Override
    public void playGame() {
        System.out.println("创建子类实现playGame方法");
    }
}
package Work.Work3;

public class Test1 {
    public static void main(String[] args) {
        //使用子类实现
        IplayImpl ii = new IplayImpl();
        ii.playGame();
        //使用匿名内部类实现
        new Iplay(){
            @Override
            public void playGame() {
                System.out.println("使用匿名内部类实现");
            }
        }.playGame();
    }
}

第二小问:

package Work.Work3;

public abstract class Fun {
    abstract void fun();
}
package Work.Work3;

public class FunImpl extends Fun{
    @Override
    void fun() {
        System.out.println("创建子类实现fun方法");
    }
}
package Work.Work3;

public class Test2 {
    public static void main(String[] args) {
        //使用子类实现
        FunImpl fi = new FunImpl();
        fi.fun();
        //使用匿名内部类实现
        new Fun(){

            @Override
            void fun() {
                System.out.println("使用匿名内部类实现");
            }
        }.fun();
    }
}

第四题

第四题:

需求:

在控制台输出”HelloWorld”

自己书写,不要用idea自动生成。

interface Inter {
    void show(); 
}
class Outer { 
    //补齐代码 
}
public class OuterDemo {
    public static void main(String[] args) {
        Outer.method().show();
    }
}

答案

为ChatGPT给出(自己的实现方式不太正确,与本课教学不同):

package Work.Work4.wd;

interface Inter {
    void show();
}
class Outer {
    //补齐代码
//创建静态方法
    public static Inter method(){
        //使用匿名内部类
      return new Inter(){
            @Override
            public void show() {
                System.out.println("HelloWorld");
            }
        };
    }
}
public class OuterDemo {
    public static void main(String[] args) {
        Outer.method().show();
    }
}

第五题

第五题:

需求:

在测试类Test中创建A的对象a并调用成员方法methodA(),要求用两种方式实现

自己书写,不要用idea自动生成。

public class Test {
    public static void main(String[] args) {	
        
    }
}

//定义接口
interface InterA {
    void showA();	
}

class A {
    public void methodA(InterA a) {
        a.showA();		
    }	
}

答案:

不知道对不对。

package Work.Work5;

    public class Test {
        public static void main(String[] args) {
            A a = new A();
            a.methodA(
                    new InterA() {
                        @Override
                        public void showA() {
                            System.out.println("showA1");
                        }
                    }
            );
            //第二种
            new A().methodA(
                    new InterA() {
                        @Override
                        public void showA() {
                            System.out.println("showA2");
                        }
                    }
            );
        }
    }

    //定义接口
    interface InterA {
        void showA();
    }

    class A {
        public void methodA(InterA a) {
            a.showA();
        }
    }

第六题

第六题:

需求:

在测试类Test中创建B的对象b,并调用成员方法methodB

自己书写,不要用idea自动生成。

public class Test {
    public static void main(String[] args) {

    }
}

//定义一个接口
interface InterB {
    void showB();	
}

//目标:调用成员方法methodB
class B {
    InterB b;
    public B(InterB b){
        this.b = b;
    }
    public void methodB(){
        b.showB();		
    }
}

答案

package Work.Work6;

public class Test {
    public static void main(String[] args) {
        B b = new B(

                new InterB() {
                    @Override
                    public void showB() {
                        System.out.println("调用了showB");
                    }
                }
        );
        b.methodB();
    }
}

//定义一个接口
interface InterB {
    void showB();
}

//目标:调用成员方法methodB
class B {
    InterB b;
    public B(InterB b){
        this.b = b;
    }
    public void methodB(){
        b.showB();
    }
}

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值