JAVA—面向对象编程高级

        学习了一定基础后,开始更加深入的学习面向对象,包含static,final两个关键字,面向对象编程三大特征之继承多态。以及对于抽象类,内部类,接口,枚举,泛型的学习。

目录

1.static

(1)修饰成员变量

(2) 修饰成员变量的应用场景

(3)修饰成员方法 

(4)修饰成员方法的应用场景

(5)注意事项

(6)应用知识

代码块

单例设计模式

2.继承

(1)介绍与入门

(2)注意事项

          [1] 权限修饰符  

          [2] 单继承,Object类

          [3] 方法重写 

          [4]子类访问其他成员的特点

          [5] 子类构造器的特点

3.多态

(1)认识与入门

(2)使用好处

(3)多态下的类型转换问题

4.final

         (1)认识与了解

         (2)常量详解

5.抽象类

(1)认识与入门

(2)使用好处

(3)应用场景

6.接口

(1)概述

(2)综合案例

(3)接口的细节

7.内部类

(1)内部类概述

(2)成员内部类

(3)静态内部类

(4)局部内部类

(5)匿名内部类*

 8.枚举

(1)介绍

 (2)应用场景

9.泛型

(1)认识泛型

(2)泛型类

(3)泛型接口

(4)泛型方法,泛型通配符,上下限

(5)注意事项


1.static

            静态,修饰成员变量,成员方法。

(1)修饰成员变量

成员变量按照有无static修饰,分为两种:

  • 类变量:有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享
  • 实例变量(对象的变量):无static修饰,属于每个对象

package W.KN.d1_static;

public class Student {
    //类变量
    static String name;
    //实例变量
    int age;
}
package W.KN.d1_static;

public class Text {
    public static void main(String[] args) {
        //目标:掌握有无static修饰成员变量的用法,特点
        //1.类变量的用法
        //类名.类变量(推荐)
        Student.name = "郑大风";

        //对象.类变量(不推荐)
        Student s1 = new Student();
        s1.name = "陈清流";

        Student s2 = new Student();

        System.out.println(s1.name);
        System.out.println(Student.name);

        //实例变量的用法:属于每个对象
        s1.age = 45;
        s2.age = 123;
        System.out.println(s1.age);
        System.out.println(s2.age);

    }
}

 成员变量执行原理

类变量,与类一起加载一次,在堆内存中开辟一份空间(且只有一份),后续不论通过类或者对象访问修改的都是同一块空间。实例变量随对象的创建而创建,访问时还是通过对象的地址


(2) 修饰成员变量的应用场景

在开发中,如果某个数据只需要一份,且希望能够被共享(访问,修改),则该数据可以被定义为类变量使用。

 案例

系统启动后,要求用户类可以记住自己创建了多少个用户对象

package W.KN.d1_static;

public class User {
    //类变量:对外公开
    public static int number;
    public User(){
        //User.number++;
        //注意:在同一类中,访问自己类的类变量,可以省略类名不写
        number++;
    }

}
package W.KN.d1_static;

public class Text2 {
    public static void main(String[] args) {
        //目标:案例理解类变量的应用场景
        User u1 = new User();
        User u2 = new User();
        User u3 = new User();
        User u4 = new User();

        System.out.println(User.number);
    }
}

(3)修饰成员方法 

成员方法按照有无static修饰,分为两种:

  • 类方法:有static修饰,属于类(类和对象都可以访问)
  • 实例方法:无static修饰,属于对象(只有对象可以访问)

package W.KN.d1_static;

public class Student {
    public static void print(){
        System.out.println("HelloWorld");
    }

    //实例方法
    public void printfPass(double score){
        System.out.println("成绩"+(score >= 60 ? "及格":"不及格"));
    }

}
package W.KN.d1_static;

public class Text3 {
    public static void main(String[] args) {
         //目标:掌握有无static修饰方法的用法
        //类方法的用法
        //类名调用
        Student.print();

        Student s = new Student();
        s.print();
        s.printfPass(100);
    }
}

 成员方法执行原理

对象之所以可以调用类方法,是由于每个对象都会在堆内存中存储一份类的地址,可以通过地址去调用这些方法,至于类为什么不能调用成员方法,很简单,一是类中没有这些方法的地址,他们都在对象的空间中,二是一般这些方法都有涉及参数,类是无法访问的。

补充:  main方法


(4)修饰成员方法的应用场景

类方法最常用的应用场景是做工具类(完成一些功能,给开发人员共同使用)

优点是调用方便,提高效率。工具类没有创建对象的需求,建议将工具类的构造器私有

 案例

对于实现验证码功能出现了重复,为避免浪费空间,在工具类中定义一个类方法实现

package W.KN.d1_static;

import java.util.Random;

public class MyUtil {
    public static String creatCoe(int n){
        //2.定义两个变量,一个用来存储最终产生的随机验证码 一个用来记住可能用到的全部字符
        String code = "";
        String data = "abccdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
        Random r = new Random();
        //3.定义一个循环 产生每位随机字符
        for (int i = 0; i < n; i++) {
            int index = r.nextInt(data.length());
            code += data.charAt(index);
        }
        return code;

    }
}

(5)注意事项

  • 类方法中可以直接访问类的成员,不可以直接访问实例对象
  • 实例方法中既可以直接访问类成员,也可以直接访问实例成员
  • 实例方法中可以出现this关键字,类方法中不可以出现this关键字

 


(6)应用知识

代码块

代码块是类的5大成分之一(成员变量,构造器,方法,代码块,内部块)

 分类

静态代码块——格式:static{ }

                         特点:类加载时自动执行,类只加载一次,所以静态代码只执行一次

                         作用:完成类的初始化,比如对类的初始化赋值(成员复杂操作赋值)

 实例代码块——格式:{ }

                          特点:每次创建对象时,执行实例代码块,并在构造器前执行

                          作用:同构造器,是用来完成对象的初始化的(实例变量进行初始化赋值)

package d3_tatic;

public class Student {
    static int number = 80;
    static String name;
    //静态代码块
    static {
        System.out.println("静态代码块执行了...");
        name = "楠楠";
    }
    //实例代码块
    //用来执行一些构造器中的重复语句
    {
        System.out.println("实例代码块执行了。。。");
    }
    public Student(){
        System.out.println("无参数构造器执行了。。。");
    }
    public Student(String name){
        System.out.println("有参数构造器执行了。。。");
    }
}
package d3_tatic;

public class Text {
    public static void main(String[] args) {
        //目标:认识两种代码块,了解他们的特点和基本作用
        System.out.println(Student.number);
        System.out.println(Student.number);
        System.out.println(Student.name);

        Student s1 =new Student();
        Student s2 =new Student("楠楠");
    }
}


单例设计模式

设计模式(Design pattern)

一种问题有n种解法,最优的解法被人总结出来,称之为设计模式

 单例设计模式:  确保一个类只有一个对象 避免浪费内存

写法

  • 把类的构造器私有
  • 定义一个类变量记住类的一个对象
  • 定义一个类方法,返回对象

 应用场景

         参照 Runtime 的写法 (返回当前编译环境)

实现方式

  • 饿汉式单例:拿对象时,对象早就创建好了
  • 懒汉式单例:拿对象时,才开始创建对象
  • .......


2.继承

(1)介绍与入门

         java提供了一个关键字extends,使用可以让一个类和另一个类建立起父子关系。

继承的特点:子类能继承父类的非私有成员(成员变量,成员方法)

继承后的创建:子类的对象是由子类和父类共同完成的

package d5_extends;
//父类
public class A {
    public int i;
    public void print1(){
        System.out.println("==print1==");
    }

    private int j;
    private void print2(){
        System.out.println("==print2");
    }
}
package d5_extends;
//子类
public class B extends A{
    public void printf3(){
        System.out.println("==print3==");
        System.out.println(i);//子类可以世界使用父类公开的成员
        print1();
        //print2(); 父类私有的不可继承
    }
}
package d5_extends;

public class Text {
    public static void main(String[] args) {
        //目标:认识继承,掌握继承的特点
        B b = new B();
        System.out.println(b.i);
        b.print1();
        b.printf3();
    }
}

 继承的执行原理

        子类在方法区中读取时,会将自己的父类也读取一次。对于这个对象就是按照两个模式去创建的

继承的好处

         减少重复代码的编写

package d6_extends;

public class People {
    private String name;

    public String getName() {
        return name;
    }

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

package d6_extends;

public class Teacher extends People{
    private String skill;

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
}
package d6_extends;

public class Text {
    public static void main(String[] args) {
        //目标:清楚继承的好处
        Teacher t = new Teacher();
        t.setName("楠楠");
        t.setSkill("java");
        System.out.println(t);
    }
}

(2)注意事项

        [1] 权限修饰符  

        权限修饰符就是用来限制类中的成员(成员变量,成员方法,构造器,代码块...)能够访问的范围。

修饰符在本类中同一个包下的其他类里任意包下的子类里任意包的任意类里
private
省缺
protected
public

                                private  <  省缺   <  protected  <   public

package d9_modifer;

public class Fu {
    private void privateMethod(){
        System.out.println("private");
    }

    void Method(){
        System.out.println("省缺");
    }

    protected void protectedMethod(){
        System.out.println("protected");
    }

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

    public void text(){
        privateMethod();
        Method();
        protectedMethod();
        publicMethod();
    }
}

         [2] 单继承,Object类

        java是单继承的,类不支持多继承,但是支持多层继承,java中所有类都是继承于Object类。


        [3] 方法重写 

              当子类觉得父类中某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称,参数列表一致的方法去覆盖父类的方法。重写后,java遵循就近原则访问方法。 (重写后,还想访问父类的方法或者变量,使用super.方法指定访问)

package d7_feature;

public class A {
    public void print(){
        System.out.println("111");
    }

    public void printf(int a,int b){
        System.out.println("11122112");
    }
}

package d7_feature;

public class B extends A {
    //方法重写
    public void print(){
        System.out.println("222");
    }

    public void printf(int a,int b){
        System.out.println("22221313");
    }
}

package d7_feature;

public class Text {
    public static void main(String[] args) {
        B b = new B();
        b.print();
        b.printf(1,2);
    }
}

 注意事项:

  • 重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性会更好。(@Overrride)
  • 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public>protected>省缺)
  • 重写的方法返回值类型,必须于被重写的方法返回类型一致,或者范围更小。
  • 私有方法,静态方法不能被重写,如果重写会报错。

          [4]子类访问其他成员的特点

子类方法中访问其他成员(成员变量,成员方法),是依照就近原则的。


           [5] 子类构造器的特点

                子类的全部构造器,都会先调用父类的构造器,再执行自己

package d10_constructor;

class F{
    public F(){
        System.out.println("父类F的 无参数构造器 执行了");
    }
}

class Z extends F{
    public Z(){
        super();//默认存在的
        System.out.println("子类Z的 无参数构造器 执行了");
    }
    public Z(String name){
        System.out.println("子类Z的 有参数构造器 执行了");
    }
}

public class Text {
    public static void main(String[] args) {
        //目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景
        Z z = new Z();
        Z z1 = new Z("楠楠");
    }
}

this(...)调用兄弟构造器(this() 和super()必须在构造器第一行

 

package d10_constructor;

class Student{
    private String name;
    private int age;
    private String school;

    public Student(String name,int age){
        this(name,age,"中北大学");
    }
    public Student() {
    }

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

    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 String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }
}

public class Text {
    public static void main(String[] args) {
        //目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景
        //学习this调用该类的其他构造器
        Student s2 = new Student("楠楠",19);
        System.out.println(s2.getName());
        System.out.println(s2.getAge());
        System.out.println(s2.getSchool());

    }
}

3.多态

(1)认识与入门

          多态是在继承/实现情况下的一种现象,表现为:对象多态行为多态

  前提:有继承/实现关系,存在父类引用子类对象,存在方法重写(才会有行为多态)


(2)使用好处

  • 在多态形式下,右边对象是解耦合的,更便于拓展和维护。
  • 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性强,更便利

 *多态下会产生下一个问题 :多态下不能使用子类的独有功能。

package d2_OPP;

public class Student extends People{
    @Override
    public void run(){
        System.out.println("学生跑的很快");
    }

    public void text(){
        System.out.println("学生需要考试");
    }
}

package d2_OPP;

public class Teacher extends People {
    @Override
    public void run(){
        System.out.println("老师跑的气喘嘘嘘");
    }
    public void teach(){
        System.out.println("老师需要教书");
    }
}

package d2_OPP;

public class Text {
    public static void main(String[] args) {
        //理解多态的好处
        //好处1 可以实现解耦合 右边对象随时切换 后续业务随之改变
        People p1 = new Student(); //new Student
        p1.run();
        //p1.text();

        Student s = new Student();
        go(s);


        Teacher t = new Teacher();
        go(t);
    }
        //好处2 可以使用父类类型的变量作为形参,可以接收一切子类对象
        public static void go(People p){

        }


}

(3)多态下的类型转换问题

类型转换:(解决多态下不能调用子类独有方法的问题)

  • 自动类型转换:父类 变量名 = new 子类();
  • 强制类型转换:子类 变量名 = (子类)父类变量  

强制类型看转换的一个注意事项:

  • 存在继承/实现关系就可以在编译阶段进行强制类型转化,编译不报错
  • 运行时,如果发现对象的真实类型与强转后的类型不同,会报类型转换异常(ClassCastException)的错误出来
  • (使用关键字 instanceof 进行判断真实类型)
package d2_OPP;

public class Text {
    public static void main(String[] args) {
        //理解多态的好处
        //好处1 可以实现解耦合 右边对象随时切换 后续业务随之改变
        People p1 = new Student(); //new Student
        p1.run();

        //强制类型转化
        if(p1 instanceof Student) {
            Student s1 = (Student) p1;
            s1.text();
        }
        else {
            Teacher t2 = new Teacher();
            t2.teach();
        }
        //就可以执行独特功能

        Student s = new Student();
        go(s);


        Teacher t = new Teacher();
        go(t);
    }
        //好处2 可以使用父类类型的变量作为形参,可以接收一切子类对象
        public static void go(People p){
            if(p instanceof Student) {
                Student s1 = (Student) p;
                s1.run();
            }
            else {
                Teacher t2 = (Teacher) p;
                t2.run();
            }
        }

}

4.final

(1)认识与了解

                 final关键字是最终的意思,可以修饰类,方法,变量

  • 修饰类 :最终类 特点是不能被继承了
  • 修饰方法:最终方法 特点是不能被重写了
  • 修饰变量:该变量只能被赋值一次
  • (final修饰基本类型的变量,变量存储的数据不能改变)
  • (final修饰引用类型的变量 地址不能改变 但是地址指向的内容是可以改变的)
package d3_final;

public class Text {
    public static void main(String[] args) {
        //final 修饰变懒 有且仅能赋值一次 
        /*
            变量
            一。局部变量
            二。成员变量
            1.静态成员变量
            2.实例成员变量 
         */
        final int  a;
        a = 5;
       // a = 6; //第二次赋值会出错 保护数值
    }
}

//1.final 修饰类,类不能被继承 (一般用于工作类)
final class A{}

//class B extends A{}

//2.final 修饰方法 方法不能被重写

class C{
    public final void text (){}
}

/*class D extends C{
    @Override
    public void text(){}
}*/
(2)常量详解
  • 使用了static final修饰的成员变量就称为常量
  • 作用:通常用于记录系统的配置信息

                     注意:命名规范:大写英文字母,多个单词使用下划线

      常量的优势和执行原理:

  • 代码可读性好,可维护性也更好
  • 编译后,常量会进行 “宏替换

5.抽象类

(1)认识与入门

                        java 有一个关键字 abstract 抽象 用来修饰类和方法

package d4_abstrsact;
//抽象类
public abstract class A {
    //抽象方法 必须用abstract修饰,只有方法签名 一定不能有方法体
    public abstract void run();
}

抽象类的注意事项特点:

  • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类。
  • 类该有的成员成员变量,方法,构造器,抽象类都可以有。
  • 抽象类最主要的特点,抽象类不能创建对象,仅作为一特殊的父类让子类继承并实现。
  • 一个类继承抽象类必须重写抽象类的全部抽象方法。否则这个类也必须定义为抽象类。

(2)使用好处

        父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义为抽象方法。交给子类去重写实现。我们设计这样的抽象类就是为了更好的支持多态。     

package d4_abstrsact;

public abstract class Animal {
    private String name;

    public abstract void cry();

    public String getName() {
        return name;
    }

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

package d4_abstrsact;

public class Dog extends Animal {

    @Override
    public void cry() {
        System.out.println("汪汪汪、、、");
    }
}

package d4_abstrsact;

public class Cat extends Animal{

    @Override
    public void cry() {
        System.out.println("喵喵喵。。。");
    }
}

package d4_abstrsact;

public class Text {
    public static void main(String[] args) {
    Cat c = new Cat();
    Dog d = new Dog();
    c.cry();
    d.cry();
    }
}

(3)应用场景

       模板方法设计模式

        解决方法中存在重复代码的问题

写法:

  • 1.定义一个抽象类
  • 2.在里面定义两个方法;

                                一个是模板方法:把相同的代码放里面去

                                一个是抽象方法:具体实现交给子类实现

package d5_abstract;

public class Text {
    public static void main(String[] args) {
        //目标:搞清楚抽象类的应用场景之一,经常用来设计模板方法设计模式
        //场景 :学生,老师都要写一篇作文
        //开头 结尾一样,正文自由发挥
        Teacher t = new Teacher();
        t.write();

    }
}

package d5_abstract;

public abstract class People {
    // 设计模板方式方法
    //定义一个模板方法
    public void write() {
       System.out.println("\t\t\t\t\t《我的爸爸》");
       //模板方法不清楚正文部分怎么写,但是它知道子类要去写
        System.out.println(writeMain());
        System.out.println("有这样的爸爸太好了");
}
    public abstract String  writeMain();

}

package d5_abstract;

public class Teacher extends People {
    public String writeMain() {
        return "也是非常厉害";
    }
}

package d5_abstract;

public class Student extends People {

    @Override
    public String writeMain() {
       return " 厉害";
    }
}

建议 final关键字修饰模版方法 :

  • 模板方法直接给对象使用,不能被子类重写
  • 一旦子类重写了模板方法,模板方法就失效了  

6.接口

(1)概述

        java 提供了一个关键字interface ,用这个关键字可以定义一个特殊的结构:接口

 

   接口中没有构造器和代码块之类的东西 ,接口也不可以创建对象。接口是被类实现(implements)的,实现接口的类称为实现类。

 一个类可以实现多个接口(接口可以理解成干爹),实现类实现多个接口。必须重写完全部接口的全部抽象方法,否则实现类需要定义为抽象类

接口的好处:

        弥补了类单继承的不足,一个类同时实现多个接口。(拓展功能)

        让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现

package d6_interface;

public class Text {
    public static void main(String[] args) {
      //目标:搞清楚使用接口的好处
        Driver s = new A();
        s.drive();
    }
}

class A extends Student implements Driver {
    @Override
   public void drive(){
        System.out.println("会开车");
    }
}

class Student{}

interface Driver {
    void drive();
}

interface Singer{
    void sing();
}

(2)综合案例

需求:

        请涉及一个班级学生的信息管理模块,学生的数据有:姓名,性别,成绩,

功能1:要求打印出全班学生的信息。功能2:要求打印出全班学生的平均成绩。

————————————————————————————————————————

        以上业务的实现有多套方案。例如:

第一套方案能打印班级全部学生的信息,能打印班级全部学生的平均分。

第二套方案能打印出班级全部学生的信息(包括男女人数)。能打印班级全部学生的平均分(要求是去掉最高分,最低分)。

package d7_interface_demo;

import java.util.ArrayList;

public class student_mpl1 implements studentOperator {
    @Override
    public void printAllInfo(ArrayList<Student> students){
        System.out.println("======全班全部学生信息======");
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            System.out.println("姓名:"+s.getName());
            System.out.println("性别:"+s.getSex());
            System.out.println("成绩:"+s.getScore());
            System.out.println("======================");
        }
        System.out.println("打印完毕");
    }
    @Override
    public void printAverageScore(ArrayList<Student> students){
        double allScore = 0.0;
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            allScore += s.getScore();
        }
        System.out.println("平均分:"+(allScore/students.size()));
    }
}
package d7_interface_demo;

import java.util.ArrayList;

public class student_mpl2 implements studentOperator{
    @Override
    public void printAllInfo(ArrayList<Student> students){
        System.out.println("======全班全部学生信息======");
        int count1 = 0;
        int count2 = 0;
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            System.out.println("姓名"+s.getName());
            System.out.println("性别"+s.getSex());
            if(s.getSex() == '男'){count1++;}else{count2++;}
            System.out.println("成绩"+s.getScore());
            System.out.println("======================");
        }
        System.out.println("男生人数:"+count1);
        System.out.println("女生人数:"+count2);
        System.out.println("班级总人数"+students.size());
        System.out.println("打印完毕");
    }
    @Override
    public void printAverageScore(ArrayList<Student> students){
        double allScore = 0.0;
        double max = students.get(0).getScore();
        double min = students.get(0).getScore();
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            allScore += s.getScore();
            if(s.getScore() > max){max = s.getScore();}
            if(s.getScore() < min){min = s.getScore();}
        }
        System.out.println("学生的最高分:"+max);
        System.out.println("学生的最低分:"+min);
        System.out.println("平均分:"+((allScore-max-min)/students.size()-2));
    }
}
package d7_interface_demo;

import java.util.ArrayList;

public interface studentOperator {
    void printAllInfo(ArrayList<Student> students);

    void printAverageScore(ArrayList<Student> students);
}
package d7_interface_demo;

import java.util.ArrayList;

public class ClassManager {
    private ArrayList<Student> students = new ArrayList<>();
    private studentOperator stuopera = new student_mpl1();
    //private studentOperator stuopera = new student_mpl2();


    public ClassManager(){
        students.add(new Student("陈平安",'男',88));
        students.add(new Student("刘羡阳",'男',100));
        students.add(new Student("顾璨",'男',90));
        students.add(new Student("宁姚",'女',100));

    }

    //打印全班全部学生信息
    public void printInfo(){
            stuopera.printAllInfo(students);
    }

    //打印全班全部学生的平均分
    public void printScore(){
            stuopera.printAverageScore(students);
    }
}
package d7_interface_demo;

public class Text {
    public static void main(String[] args) {
        //目标:完成班级学生信息管理的案例
    ClassManager opera = new ClassManager();
    opera.printInfo();
    opera.printScore();
    }
}

(3)接口的细节

        JDK8后接口新增的三种方法(增强接口功能,便于系统维护)

package d8_jdk8;

public interface A {
    //1.默认方法:必须使用default修饰,默认会被public修饰
    //实例方法:对象访问 ,必须通过实现类
    default void text1(){
        System.out.println("默认方法");
        text2();
    }

    //2.私有方法:必须使用private修饰
    //jkk9后支持 //在接口中调用
    private void text2(){
        System.out.println("私有方法");
    }

    //3.静态方法:必须使用static修饰
    //只能使用接口名来调用
    public static void text3(){
        System.out.println("静态方法");
    }
}

        接口的多继承

便于类去实现

 接口的注意事项(了解)

  1. 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承。
  2. 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现.
  3. 一个类,继承了父类,又同时实现了接口。父类中和接口中有同名的默认方法实现类会优先用父类的。
  4. 一个类实现了多个接口,多个接口中存在同名的默认方法可以不冲突,这个类重写该方法即可。


7.内部类

(1)内部类概述

内部类是类中的五大成分之一(成员变量,方法,构造器,内部类,代码块),一个类定义在另一个类的内部,这个类就是内部类


(2)成员内部类

        类中的一个普通成员,类似前面学过的普通的成员变量,成员方法(注意访问特点)

 注意事项:

        1.jdk16后支持内部类创建静态成员变量

        2.内部类创建对象的格式:外部类名.内部类名 对象名 = new 外部类 (...)new 内部类(...);


(3)静态内部类

        有static修饰的内部类,属于外部类自己持有。


(4)局部内部类

        局部内部类是定义在方法中,代码中,构造体等执行体(鸡肋语法)


(5)匿名内部类*

        就是一种特殊的内部类;所谓匿名:指程序员不需要为这个类声明名字

使用场景: 通常作为一个参数传输给方法

 

实际应用场景:

 

package d2_inner;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Text4 {
    public static void main(String[] args) {
        //拓展:搞清楚匿名内部类在着真实开发中的使用场景
        //GUI编程
        //1.创建窗口
        JFrame win  = new JFrame("登录界面");
        JPanel panel = new JPanel();
        win.add(panel);
        JButton btn = new JButton("登录");
        win.add(btn);

        // 给按钮绑定单击事件监听器
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(win,"欢迎");

            }
        });
        //最终的核心目的是:简化代码
        win.setSize(400,400);
        win.setLocationRelativeTo(null);
        win.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        win.setVisible(true);
    }
}


 8.枚举

        枚举是一种特殊类

(1)介绍

  1. 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每一个常量记住的都是枚举类的一个对象。
  2. 枚举类的构造器都是私有的(写与不写都只能是私有),因此枚举类对外不能创建对象。
  3. 枚举都是最终类,不可以被继承,枚举类中从第二行开始可以定义类的其他各种成员。
  4. 编译器为枚举类新增了几个方法,并且枚举类都是继承JAVA.long.Enum类。

package d3_enum;

public class Text {
    public static void main(String[] args) {
        //目标 认识枚举
        A a1 = A.X ;
        System.out.println(a1);
        
        //枚举类提供一个一些额外的API
        A[] as = A.values(); //拿到全部对象
        A a3 = A.valueOf("Z");
        System.out.println(a3.name());
        System.out.println(a3.ordinal()); //索引


    }
}

 

 (2)应用场景

 应用场景: 用来表示一组信息,然后作为参数进行传输

                    作为信息分类


9.泛型

(1)认识泛型

     泛型:定义类,接口,方法时,同时声明了一个或者多个类型变量<E>,称为泛型类,泛型接口,泛型方法,统称为泛型

      作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力,这样可以避免强制类型转换,及其可能出现的异常

       泛型的本质:把具体的数据类型作为参数传给类型变量 


(2)泛型类

      

 

package d5_generics;

public class List <E>{
    private Object [] arr = new Object[10];
    private int size;

    public boolean add(E e){
        arr[size++] = e;
        return true;
    }

    public E get (int index){
        return (E) arr[index];
    }
}

(3)泛型接口

package d5_generics;

import java.util.ArrayList;

public interface Data<T> {
    void add(T t);
    ArrayList<T> getByName(String name);
}

       泛型接口的类型变量建议使用大写英文字母


(4)泛型方法,泛型通配符,上下限

package d5_generics;

import java.util.ArrayList;

public class Text3 {
    public static void main(String[] args) {
        //目标:掌握泛型方法的定义和使用
        String rs = test("java");
       
        Dog d = test(new Dog());
        System.out.println(d);
    }
   
    //泛型方法
    public static <T> T test (T t){
        return t;
    }
    
    //使用extends限制输入类型 是car或者car的子类
    public static <T extends car > void go(ArrayList<T> car){
        
    }
    //? 通用符 使用泛型可以代表一切类型 一样可以限制 ?extends car(上限) ?super car(下限)
    public static  void go1(ArrayList<? extends car> car){

    }
}

(5)注意事项

擦除问题

        泛型是工作在编译阶段的,一旦程序编译成class文件。Class文件中就不存在泛型了,这就是泛型擦除。(底层还是基于Object类型)

        泛型不支持基本数据类型。只能支持对象类型(引用数据类型)。


                                                                                                                        学习时间:2024.8.4

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值