Java学习笔记===》9.面向对象进阶2

面向对象进阶

一、抽象类

1.抽象方法

共性的 行为(方法)抽取到父类之后,由于每一个子类执行的类容是不一样的,所以,在父类中不能确定具体的方法体,该方法就可以定义为抽象方法****

2.抽象类:

如果一个类中存在抽象方法,那么该类就必须声明为抽象类

3.抽象方法和抽象类的定义格式

(1)抽象方法的定义格式

public abstract 返回值类型 方法名 (参数列表){};

(2)抽象类的定义格式

public abstract class 类名{};

4.抽象类和抽象方法的注意事项

🔺抽象类不能实例化(不能创建对象)

🔺抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类

🔺抽象类可以有构造方法

🔺抽象类的子类要么是抽象类,要么重写抽象类中的所有抽象方法

package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test01;

//有抽象方法的一定是抽象类
public abstract class Person {
    private String name;
    private int age;


    //抽象类中可以有构造方法(空参、含参)
    //这里的构造方法的作用:当创建子类对象时,给属性进行赋值的
    public Person() {
    }

    public Person(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 work();

    //抽象类中不一定有抽象方法,
    public void sleep(){
        System.out.println("睡觉");   //抽象类中没有抽象方法不会报错
    }
}
package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test01;

//抽象类的子类要么是抽象类
//要么是重写抽象类中的所有方法
public  class Student extends Person {


    //重写所有方法

    public Student() {
    }

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

    @Override
    public void work() {
        System.out.println("学生的工作i时学习");
    }
}
package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test01;

//抽象类的子类要么是重写所有方法,要么自己也是抽象类

//这里抽象类的子类Teacher自己是 抽象类
//但是抽象类不能创建自己的对象
//如果要创建自己的类,就需要新建这个类的子类重写这个类的所有方法
public abstract class Teacher extends Person{
}
package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test01;

public class Test {
    public static void main(String[] args) {
        //1.抽象类不能(实例化)创建对象
        // Person p = new Person();  //Person是抽象的; 无法实例化

        Student s = new Student("zhangsan",22);

        System.out.println(s.getName()+","+s.getAge());
    }
}
abstract练习

需求:
青蛙frog 属性:名字,年龄 行为:吃虫子,喝水
狗dog 属性:名字,年龄 行为:吃骨头,喝水
山羊sheep 属性:名字,年龄 行为:吃草,喝水

package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test02;

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 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 void drink(){
        System.out.println("喝水");
    }
}
package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test02;

public  class Dog extends Animal {

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

    public Dog() {
    }

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

package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test02;

public  class Frog extends Animal {

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

    public Frog() {
    }

    public Frog(String name, int age) {
        super(name, age);
    }
}
package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test02;

public  class Sheep extends Animal {

    @Override
    public void eat() {
        System.out.println("山羊在吃草");
    }

    public Sheep() {
    }

    public Sheep(String name, int age) {
        super(name, age);
    }
}
package com_03_mianxaingduixiang.Demo_06_Abstract.abstract_test02;
/*
需求:
青蛙frog          属性:名字,年龄    行为:吃虫子,喝水
狗dog             属性:名字,年龄    行为:吃骨头,喝水
山羊sheep         属性:名字,年龄    行为:吃草,喝水
 */
public class Test {
    public static void main(String[] args) {
        Dog d = new Dog("大黄",12);
        Frog f = new Frog("小绿",4);
        Sheep s = new Sheep("肖恩",9);

        System.out.println(d.getName()+","+d.getAge());
        d.eat();d.drink();
        System.out.println(f.getName()+","+f.getAge());
        f.eat();f.drink();
        System.out.println(s.getName()+","+s.getAge());
        s.eat();s.drink();

    }
}

5.抽象类和抽象方法的意义

(1)疑问

把子类中共性的内容抽取到父类之后,由于方法体不确定,需要定义为抽象。子类使用时需要重写,但如果不抽取到父类中,直接写在子类里面不是更节约代码

★强制子类必须按照同一种格式进行重写(让代码格式统一)

二、接口

为什么会有接口?

接口:就是一种规则,是对行为的抽象

(1).接口的定义和使用

①接口关键字interface来定义

​ Public interface 接口名 { };

②接口不能实例化(不能创建对象)

③接口和类之间是实现关系,通过implements关键字表示

​ public class 类名 implements 接口名 { }

④接口的子类称为实现类

​ 在实现类中,要么重写接口中的所有抽象方法(使用更多),要么自身是抽象类

⑤注意:

(1)接口和类的实现关系,可以单实现,也可以多实现

​ public class 类名 implements 接口名1,接口名2 { };

(2)实现类还可以在继承一个类的同时实现多个接口

​ public class 类名 extends 父类 implements 接口名1,接口名2 { } ;

⑥接口练习

package com_03_mianxaingduixiang.Demo_07_inteface.interface_test01;

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 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();


}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test01;

public interface swim {
      public abstract void swimming();
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test01;

import jdk.swing.interop.SwingInterOpUtils;

public class Dog extends Animal implements swim{

    public void swimming(){
        System.out.println("狗会狗刨");
    }

    public Dog() {
    }

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

    @Override
    public void eat() {
        System.out.println("狗在吃骨头");
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test01;

public class Frog extends Animal implements swim {

    public void swimming(){
        System.out.println("青蛙会蛙泳");
    }

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

    public Frog() {
    }

    public Frog(String name, int age) {
        super(name, age);
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test01;

public class Rabbit extends Animal{
    
    @Override
    public void eat() {
        System.out.println("兔子吃胡萝卜");
    }

    public Rabbit() {
    }

    public Rabbit(String name, int age) {
        super(name, age);
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test01;

public class Test {
    public static void main(String[] args) {
        Rabbit r = new Rabbit("xiaobai",2);
        r.eat();
        Dog d = new Dog("dahuanug",3);
        d.eat();d.swimming();
        Frog f = new Frog("xiaolv",2);
        f.eat();f.swimming();
    }
}

(2)接口里面成员的特点

①成员变量

​ 接口中的成员变量只能是常量

​ 默认修饰符 : public static final

②构造方法

​ 接口中不能有构造方法

③成员方法

默认修饰符:public abstract

​ ★jdk7以前:接口中只能定义抽象方法

​ ★jdk8的新特性:接口中可以定义有方法体的方法

​ ★jkd9的新特性:接口中可以定义私有方法

(3)接口和类之间的关系

①类和类之间的关系

继承关系,只能单继承,不能多继承,但是可以多层继承

②类和接口的关系

实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口

③接口和接口的关系

继承关系,可以单继承,也可以多继承

细节:如果实现类实现了最下面的子接口的话,那么就需要重写所有的抽象方法

package com_03_mianxaingduixiang.Demo_07_inteface.interface_test04;
//接口1
public interface inter1 {
    public abstract void method1();
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test04;
//接口2
public interface inter2 {
    public abstract void method2();
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test04;
//接口3,继承了接口1和接口2
public interface inter3 extends inter1,inter2 {
    public abstract void method3();
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test04;
//实现类
public class Interimpl implements inter3{
    @Override
    public void method3() {

    }

    @Override
    public void method1() {

    }

    @Override
    public void method2() {

    }
}

(4)JDK8 开始接口中新增的方法

1.JDK 7以前

接口中只能定义抽象方法

2.JDK 8的新特性

接口中可以定义有方法体的方法(默认、静态)

(1)默认方法

★允许在接口中定义默认方法,需要使用关键字default修饰

​ 🔺作用:解决接口升级的问题

★接口中默认方法的定义格式:

​ 🔺public default 返回值类型 方法名 (参数列表){…};

​ 🔺示例:public default void show(){…};

★接口中默认方法的注意事项;

​ 🔺默认方法不是抽象方法,所以不强制被重写,但如果被重写,重写的时候去掉default关键字

​ 🔺public 可以省略,但是default不可以省略

​ 🔺如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写

package com_03_mianxaingduixiang.Demo_07_inteface.interface_test07;

public interface interB {


    //默认方法
    //如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
    //两个接口中含有相同名字的方法,那么实现类里面就必须重写这个方法
    public default void show2(){
        System.out.println("interB接口中的默认方法------show2");
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test07;

public interface interB {


    //默认方法
    //如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
    //两个接口中含有相同名字的方法,那么实现类里面就必须重写这个方法
    public default void show2(){
        System.out.println("interB接口中的默认方法------show2");
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test07;

public class interImpl implements interA,interB {
    @Override
    public void show1() {
        System.out.println("重写之后的抽象方法show1");
    }

    //这里默认方法不重写也不会报错

    //但如果要重写就必须要去掉default关键字


    @Override
    public void show2() {
        System.out.println("重写之后的默认方法show2");
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test07;
/*
★接口中默认方法的定义格式:
     🔺public  default  返回值类型  方法名  (参数列表){...};
     🔺示例:public  default  void  show(){...};
  ★接口中默认方法的注意事项;
     🔺默认方法不是抽象方法,所以不强制被重写,但是如果被重写,重写的时候去掉default关键字
     🔺public 可以省略,但是default不可以省略
     🔺如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
 */
public class Test {
    public static void main(String[] args) {
        //创建实现类对象
        interImpl i1 = new interImpl();
        i1.show1();
        i1.show2();

    }
}
(2)静态方法

★允许在接口中定义静态方法,需要用static修饰

★接口中静态方法的定义格式:

​ 🔺格式:public static 返回值类型 方法名(){…};

​ 🔺示例:public static void show ( ) {…};

★接口中静态方法的注意事项:

​ 🔺静态方法只能通过接口名调用,不能通过实现类或者对象名调用

​ 🔺public 可以省略,但是static不可以省略

package com_03_mianxaingduixiang.Demo_07_inteface.interface_test08;

public interface interA {

    //接口中的抽象方法
    public abstract void  method();


    //接口中的静态方法不能被重写
    public static void show(){
        System.out.println("interA接口中的静态方法-------show");
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test08;

public class interImpl implements interA{

    @Override
    public void method() {
        System.out.println("重写之后的method抽象方法");
    }

    public static void show(){
        System.out.println("实现类里面的静态方法----show");
    }
}
package com_03_mianxaingduixiang.Demo_07_inteface.interface_test08;

import com_03_mianxaingduixiang.Demo_07_inteface.interface_test02.inter;

/*
★允许在接口中定义静态方法,需要用static修饰
★接口中静态方法的定义格式:
  🔺格式:public  static  返回值类型  方法名(){...};
  🔺示例:public  static  void  show ( ) {...};
★接口中静态方法的注意事项:
  🔺静态方法只能通过接口名调用,不能通过实现类或者对象名调用
  🔺public 可以省略,但是static不可以省略
 */
public class Test {
    public static void main(String[] args) {
        //调用接口中的静态方法
        interA.show();

        //调用实现类中的静态方法
        interImpl.show();

        //子类把从父类继承下来的虚方法表里面的方法进行覆盖了,这才叫重写
    }
}

3.JDK 9的新特性

接口中可以定义私有方法

定义私有方法,用来服务接口中的重复代码

(1)定义格式

①格式1:private vod show(){}

private void 方法名 (参数列表){ }

②private static void show () {}

private static 返回值类型 方法名(参数列表){}

4.总结:

(1)jdk7以前:接口中只能定义抽象方法

(2)jdk8:接口中可以定义有方法体的方法(默认、静态)

(3)jdk9:接口中可以定义私有方法

(4)私有方法分两种:

​ 1.普通的私有方法(给默认方法服务的)2.静态的私有方法(给静态方法服务的)

(5)接口的应用

1.接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了

2.当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态

​ 例如:public static void (interface A){}

(6)适配器设计模式

1.设计模式(Design Patern):

​ 是一套被反复利用、多打湖人只晓得、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性

简单理解:设计模式就是各种套路

2.适配器设计模式:

解决接口与接口实现类之间的矛盾问题

总结:

1.当一个接口中抽象方法过多,但是我们只要使用其中一部分的时候,就可以用适配器设计模式

2.书写步骤:

编写中间类 XXXAdapter,实现对应的接口

对接口中的抽象方法进行空实现(重写所有方法,但不写方法体)

让真正的实现类继承中间类,并重写需要用到的方法

为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰

三、内部类

1.什么是内部类:

在一个类的里面再定义一个类

public class Outer{  //外部类
    public  class Inner{		//内部类
    }
}
public class Test{		//外部其他类
    public  sattic void main(String []args){
        
    }
}

什么时候会用到内部类呢:

B类表示的事务是A类的一部分,且B单独存在没有意义

类的五大成员:属性、方法、构造方法、代码块、内部类

2.为什么要学习内部类:

需求:写一个JavaBean类描述汽车

属性:汽车的品牌,车龄,颜色,发动机的品牌,使用年限

public class Car{		//外部类
    String carname;
    int carAge;
    String carColor;
    //内部类表示的事务是外部类的一部分
    //且内部类单独出现没有任何意义
    class Engine{		//内部类
        String engineName;
        int EngineName;
    }
}

3.内部类的访问特点:

(1)内部类可以直接访问外部内的成员

(2)外部类要访问内部类的成员,必须要创建对象

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test01;

public class Car {
     String carName;
     int carAge;
     private String carColor;

     public void show2(){
         //外部类可以访问外部类的所有成员
         System.out.println(carAge+","+carName+","+carColor);
         //但不能直接访问内部类的成员,会报错
         //System.out.println(EngineName+","+EngineAge);
         //如果非要访问内部类的成员,就必须要创建对象
         Engine e = new Engine();
         System.out.println(e.EngineName+","+e.EngineAge);
     }
    class Engine {
         private String EngineName;
         int EngineAge;

         public void show(){
             //内部类可以直接访问外部类的成员,包括私有
             System.out.println(carAge+","+carName+","+carColor);
             //内部类也可以直接访问内部类里面的所有成员,包括私有
             System.out.println(EngineName+","+EngineAge);

         }
    }
}

4.成员内部类

(1)成员内部类的代码如何书写

★ 成员内部类是写在成员位置的,属于外部类的成员(类中方法外)

★成员内部类可以被一些修饰符所修饰,比如:private(本类里面)、默认(本包下的所有子类)、protected(本包或其他包的子类里面)、public(所有位置)、static等

★在成员内部类的里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量

public class Car{		//外部类
    String carname;
    int carAge;
    String carColor;
   
    class Engine{		//成员内部类
        String engineName;
        int EngineName;
    }
}

(2)如何创建成员内部类的对象

①在外部内中编写方法,对外提供内部类的对象

使用场景:当内部类被private修饰时,在外部类编写方法,对外提供内部类对象

②可以在外部类直接创建:当成员内部类被非私有修饰时直接创建

外部类名.内部类名. 对象名 = 外部类对象.内部类对象;

package com_03_mianxaingduixiang.InnerClass_test02;

public class Outer {

    private class Inner{
        //在内部类里面声明静态变量
        //但是在JDK16之前不能在内部类里面声明静态变量
        //static int a = 10;


    }
    //当内部类是私有的时候,可以在外部类里面内部类外面创建创建方法,对外提供内部类对象
    public Inner getInstance(){
        return new Inner();
    }
}
package com_03_mianxaingduixiang.InnerClass_test02;

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

        //创建对象的方式
        //类名.对象名 = new 类名();
        //Student s = new Stutdent();

        //我要创建的是谁的对象===》内部类的对象
        //如何创建成员内部类的对象
        //①在外部内中编写方法,对外提供内部类的对象
        //②可以在外部内直接创建内部类对象:
        // 外部类名.内部类名. 对象名 = 外部类对象   .成员内部类对象;
        //  Outer .Inner      oi = new Outer().new Inner();  内部类私有的时候不能直接创建对象

        Outer o = new Outer();
        //调用方法,获取内部类的对象
        System.out.println(o.getInstance());
    }
}

(3)成员内部类如何获取外部类的成员变量

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test03;

public class Outer {
    private int a = 10;


    class Inner{

        private int a = 20;


        public  void  show(){
            int a = 30;
            Outer o1 = new Outer();
            System.out.println(this.a);     //20
            System.out.println(a);          //30
            System.out.println(o1.a);        //10
            
            //Outer.this:表示获取了外部类对象的地址值
            System.out.println(Outer.this.a);   //10
        }
    }
}
package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test03;

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

        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }
}

在这里插入图片描述

(4)总结:

①内部类的分类

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

②什么是成员内部类

写在成员位置的,属于外部类的成员

③获取成员内部类对象的两种方式

​ 方式一:当成员内部类被private修饰时,在外部类中编写方法,对外提供内部类对象

​ 方式二:当成员内部类被非私有修饰时,直接创建对象

​ 外部类 . 内部类 对象名 = new 外部类(). new内部类();

​ Outer . Inner oi = new Outer . new Inner();

④外部类成员和内部类成员变量重名时,在内部类如何访问

​ System.out.println( Outer . this . 变量名);

5.静态内部类

静态内部类只能访问外部类中的静态变量和静态方法,如果像访问非静态的需要创建外部类的对象

public class Outer{		//外部类
    String name;
    int Age;
    int color
    
    static class Inner{	//静态内部类
        String name;
        int Age;
    }
}

1.静态内部类

(1)创建静态内部类的对象

外部类名 . 内部类名 对象名 = new 外部类名 . 内部类名();(要和非静态的创建对象区分)

(2)调用非静态方法的格式

先创建对象,用对象调用

(3)调用静态方法的格式

外部类名 . 内部类名 . 方法名();

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test04;

public class Outer {

    int a = 10;
    static int b = 20;


    //静态内部类
    static class Inner{
        public void show1(){
            Outer o = new Outer();
            System.out.println(o.a);
            System.out.println(b);
            System.out.println("非静态的方法被调用了");
        }
        public static void show2(){
            Outer o = new Outer();
            System.out.println(o.a);
            System.out.println(b);
            System.out.println("静态的方法被调用了");
        }
    }
}

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test04;

import javax.annotation.processing.SupportedAnnotationTypes;

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

        Outer.Inner oi = new Outer.Inner();
        oi.show1();

        //虽然也可以直接调用静态方法,但是不提倡
        //oi.show2();

        Outer.Inner.show2();
    }
}
(4)总结
(1)什么是静态内部类

静态内部类是一种特殊的成员内部类

(2)直接创建静态内部对象的方式

Outer .Inner oi = new Outer.Inner();

外部类名 . 内部类名 对象名 = new 外部类名 . 内部类名();

(3)如何调用静态内部类中的方法?

​ 静态内部类只能访问外部类中的静态变量和静态方法

​ 如果想访问非静态的需要创建外部类的对象

非静态方法:先创建对象,用对象调用

静态方法:外部类名 . 内部类名 . 方法名();

6.局部内部类

(1)什么是局部内部类

​ 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量

(2)局部内部类的特点

​ 外界无法直接使用,需要在方法内部创建对象并使用

​ 该类可以直接访问外部类的成员,也可以访问方法内的局部变量

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test05;

/*
   将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量

   外界无法直接使用,需要在方法内部创建对象并使用

   该类可以直接访问外部类的成员,也可以访问方法内的局部变量
 */
public class Outer {

    int b = 20;

    public void show1(){
        int a = 10;

        //局部内部类
        class Inner{
            String name;
            int age;

            public void show2(){
                //局部内部类可以直接访问外部类的成员和局部变量
                System.out.println(b);  //成员变量
                System.out.println(a);  //局部变量
                System.out.println("局部内部类中的show2方法");
            }

            //jdk16之后可以定义静态
            //public static void show3(){
            public static void show3(){
                System.out.println("局部内部类中的show2方法");
            }
        }

        //在方法里面创建局部内部类的对象
        Inner i = new Inner();
        System.out.println(i.name+","+i.age);
        //创建对象调用局部内部类里面的方法
        i.show2();
        i.show3();
        //使用类名调用静态方法
        Inner.show3();
    }
}
package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test05;

public class Test {
    public static void main(String[] args) {
        //外界无法直接使用局部内部类,需要在方法内部创建对象并使用
        //无法直接使用show方法里面的局部变量a
        Outer o = new Outer();
        o.show1();
    }
}

7.匿名内部类

(1)什么是匿名内部类

🔺匿名内部类本是上就越是隐藏了名字的内部类,这个内部类可以写在成员位置,也可以写在局部位置,只不过名字被隐藏了

(2)格式

	new 类名或者接口名(){	//类名表示继承关系,接口表示实现关系
        重写方法
	}

🔺格式的细节:这个格式里面包含了三部分:继承/实现 、方法重写 、创建对象

例如:

new Inter(){
    public void show(){
        
    }
}

(3)使用场景

①当方法的参数是接口或者类时

②以接口为例,可以传递这个接口的实现类对象

③如果实现类只要使用一次,就可以用匿名内部类简化代码

代码演示:

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test06;

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

        //编写匿名内部类的代码
        new Swim(){
            @Override
            public  void swim(){
                System.out.println("重写之后的swim方法");
            }
        };
    }
}
package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test06;

public interface Swim {
    public abstract void swim();
}

扩展:

package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test06;

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

        //编写匿名内部类的代码
        new Swim(){
            @Override
            public  void swim(){
                System.out.println("重写之后的swim方法");
            }
        };

        method(
                new Animal(){
                    @Override
                    public void eat(){
                        System.out.println("狗吃骨头");
                    }
                }
        );
//        new Animal(){
//            @Override
//            public void eat(){
//                System.out.println("重写之后的eat方法");
//            }
//        };
    }

    public static void method(Animal a){

    }
}
package com_03_mianxaingduixiang.Demo_08_InnerClass.InnerClass_test06;

public class Test2 {
    public static void main(String[] args) {
          //匿名内部类的格式
//        new 类名(继承关系)/接口(实现关系)(){
//            重写方法
//        }


        //这个整体可以理解为Swim接口实现类的对象
        Swim s = new Swim(){
            @Override
            public void swim() {
                System.out.println("重写之后的swim方法");
            }
        };
        //编译看左边,运行看右边,对象调用方法
        s.swim();

        //匿名实现类整体是是一个对象,所以可以调用方法
        new Swim(){
            @Override
            public void swim() {
                System.out.println("重写游泳方法");
            }
        //用整体来调用方法
        }.swim();
    }
}

四、拼图小游戏

1.目的

(1)将面向对象的知识点贯穿起来(循环、字符串、判断、集合)

(2)锻炼逻辑思维能力

(3)知到所学知识点在实际开发中的应用场景

涉及到的知识点;

封装、继承、多态、抽象类、接口、内部类、集合、字符串、数组、循环、判断

2.游戏主界面添加组件

(1)JFrame:(主窗体)

(2)JMenuBar:菜单

(3)JMenu:菜单选项

(4)JLabel:容器管理(文字、图片等)

在这里插入图片描述

3.事件

(1)定义:

就是可以被组件识别的操作,也就是当我们对组件干了某件事之后,就会执行相应的代码

(2)事件的核心要素

①事件源:按钮、图片、窗体

②事件:指某些操作鼠标点击、鼠标划入

③绑定监听:当事件源上发生了某个事件,则会执行某些代码

(3)常见的事件监听

①KeyListener:键盘监听

Modifier and Type方法描述
voidkeyPressed ( KeyEvent e )按下键时调用
voidkeyReleased ( KeyEvent e )当键已被释放时调用
voidkeyTyped ( KeyEvent e )键入键时调用

**细节1:**如果我们按下一个按键没有松开,那么会重复的去调用keyPressed方法

**细节2:**键盘里面众多案件,如何进行区分?

​ 每一个按键都有一个编号与之对应,调用方法e.getKeyCode()可以获取到每一个按下的按键的编号

package com.kinbow.test;

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class MyJFrame3 extends JFrame implements KeyListener {

    public MyJFrame3 (){
        //设置界面的宽高
        this.setSize(603,688);
        //设置界面的标题
        this.setTitle("我的界面");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //取消默认的居中放置,只有取消了才会按照XY轴的形式添加组件
        this.setLayout(null);
        //给整个窗体添加键盘监听
        //调用者this:表示本类对象,就是当前的界面对象,表示我要给整个页面添加监听
        //addKeylistener :表示要给本界面添加键盘监听
        //参数this : 表示当事件被出发之后,会执行本类中的对应代码
        this.addKeyListener(this);
        //显示界面
        this.setVisible(true);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("按下不松");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        System.out.println("释放");
        //e.getKeyCode() : 获取键盘上每一个按键的编号 与ASCII码表没有关系
        int code = e.getKeyCode();
        System.out.println("按下的按键是"+code);
        if (code == 65){
            System.out.println("现在按的是A");
        }else if (code == 66){
            System.out.println("现在按的是B");
        }
    }
}

②MouseListener:鼠标监听机制

划入动作

按下动作

松开动作

划出动作

如果想监听一个按钮的单击事件,有以下三种方式

★动作监听★鼠标监听中的单击事件★鼠标监听中的松开事件★

package com.kinbow.test;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;

public class MyJFrame2 extends JFrame implements MouseListener {
    //创建一个按钮对象
    JButton jbt1 = new JButton("点我改变大小");
    //创建一个按钮对象
    JButton jbt2 = new JButton("点我改变位置");
    public MyJFrame2 (){
        //设置界面的宽高
        this.setSize(603,688);
        //设置界面的标题
        this.setTitle("我的界面");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //取消默认的居中放置,只有取消了才会按照XY轴的形式添加组件
        this.setLayout(null);

        //给按钮设置宽高
        jbt1.setBounds(0,0,100,50);
        //给按钮绑定鼠标事件
        jbt1.addMouseListener(this);

        //给按钮设置宽高
        jbt2.setBounds(100,0,100,50);
        //给按钮添加事件
        jbt2.addMouseListener(this);

        //显示界面
        this.setVisible(true);

        //将按钮添加到窗体中
        this.getContentPane().add(jbt1);
        this.getContentPane().add(jbt2);
    }




    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("这是个单击事件");
    }

    @Override
    public void mousePressed(MouseEvent e) {
        System.out.println("这是个按下不松事件");
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        System.out.println("这是个松开事件");
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        System.out.println("这是个划入事件");
    }

    @Override
    public void mouseExited(MouseEvent e) {
        System.out.println("这是个划出事件");
    }
}
方法摘要
Modifier and type方法描述
voidmouseClicked(MouseEvent e)在组件上单击(按下并释放)鼠标按钮时调用
voidmouseEntered(MouseEvent e)当鼠标进入组件时调用
voidmouseExited(MouseEvent e)当鼠标退出组件时调用
voidmousePressed(MouseEvent e)在组件上按下鼠标按钮时调用
voidmouseReleased(MouseEvent e)在组件上释放鼠标按钮时调用

③ActionListener:行为(动作)监听

package com.kinbow.test;

import javax.swing.*;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

public class MyJFrame extends JFrame implements ActionListener{

    //创建一个按钮对象
    JButton jbt1 = new JButton("点我改变大小");
    //创建一个按钮对象
    JButton jbt2 = new JButton("点我改变位置");
    public MyJFrame() {
        //设置界面的宽高
        this.setSize(603,688);
        //设置界面的标题
        this.setTitle("我的界面");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //取消默认的居中放置,只有取消了才会按照XY轴的形式添加组件
        this.setLayout(null);



        //给按钮设置宽高
        jbt1.setBounds(0,0,100,50);
        //给按钮添加事件
        jbt1.addActionListener(this);

        //给按钮设置宽高
        jbt2.setBounds(100,0,100,50);
        //给按钮添加事件
        jbt2.addActionListener(this);

        //显示界面
        this.setVisible(true);

        //将按钮添加到窗体中
        this.getContentPane().add(jbt1);
        this.getContentPane().add(jbt2);
    }


    @Override
    public void actionPerformed(ActionEvent e) {
        //对当前按钮进行判断

        //获取当前被操作的按钮的对象
        Object source = e.getSource();
        if (source == jbt1){
            jbt1.setSize(200,200);
        }else if (source == jbt2){
            Random r = new Random();
            jbt2.setLocation(r.nextInt(500),r.nextInt(500));
        }
    }
}
美化界面

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值