前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础重构-面向对象

Java基础重构-面向对象

作者头像
Petterp
发布2022-02-09 12:49:19
6500
发布2022-02-09 12:49:19
举报
文章被收录于专栏:JetPack

Java 是面向对象的程序设计语言,类是面向对象的重要内容,可以把了当成一种自定义类型。可以使用类来定义变量,这种类型的变量统称为引用变量。

static 是一个特殊的关键字,它可用于修饰方法,成员变量等成员。static 修饰的成员表明他属于这个类本省,而不属于该类的单个实例,因为通常把 static 修饰的成员变量和 方法 也成为类变量,类方法。不使用 static 修饰的普通方法,成员变量则属于该类的单个实例,而不属于该类。因为通常把不使用 static修饰的成员变量和方法也成为实例变量,实例方法。

对象的this引用是什么?

Java 提供了一个this 关键字,this关键字总是指向调用该方法的对象,更具 this 出现位置的不同,this作为对象的默认引用有两种情形。

  1. 构造器中引用该构造器正在初始化的对象
  2. 在方法中引用调用该方法的对象。

this关键字最大的作用就是让类中一个方法,访问该类里的另一个方法或实例变量。 this可以代表任何对象,当this出现在某个方法体重是,它所代表的对象是不确定的,但它的类型是确定的,他所代表的对象 只能是当前类;只有当这个方法被调用时,它所代表的对象才被确定下来,谁在调用这个方法,this就代表谁。 大部分时候,一个方法访问该类中定义的其他方法,成员变量时加不加this前缀的效果是完全一样的。但是对于static 修饰的方法而言,则可以使用类来直接调用该方法,如果在 static 修饰的方法中使用 this关键字,则这个关键字就无法指向合适的对象。所以,satatic 修饰的方法不能使用 this引用,所以static 修饰的方法不能访问不使用 static 修饰的普通成员,因此 Java 语法规定: 静态成员不能直接访问非静态成员。 也可以将 this 作为返回值,如果某个方法把 this 作为返回值,则可以多次连续调用同一个方法,从而使得代码更加简洁。但是,这种把 this作为返回值的方法可能造成实际意义上的模糊。

代码语言:javascript
复制
public class MyClass {
    private static int age;

    public static void main(String[] args) {
        new MyClass().vo().vo().vo();
    }

    private MyClass vo() {
        ++age;
        System.out.println(age);
        return this;
    }

}
为什么static成员不能直接访问非静态成员?

static 是一个特殊的关键字,它可用于修饰方法,成员变量等成员。static 修饰的成员表明他属于这个类本身,而不属于该类的单个实例。而我们非static 修饰的变量它属于的是实例的变量,所以stati成员不能直接

访问静态成员

为什么同一类里,静态和非静态方法可以相互调用?

因为Java里的方法不能独立存在,他必须属于一个类或一个对象,因此方法不能像函数那样被独立执行,执行方法时必须使用类或对象来作为调用者,同一个类的一个方法调用另外一个方法时,如果被调方法时普通方法,则使用默认使用 this 作为调用者;如果被调方法是静态方法,则默认使用类作为调用者。也就是说,表面上看起来某些方法可以被独立执行,但实际上环视使用this或者 类 作为调用者。

Java的参数传递中可以引用传递吗?

不可以,Java的参数传递方式只有一种,值传递。所谓值传递,就是将实际参数值的副本(复制品)传入方法内,而参数本身不会受到影响。

我们有时候见到 使用 参数传递 某些对象。看起来好像是引用传递,但其实不是,这里传递的也只是一个对象在内存中的的地址而已,并不是真正的把 对象引用传递过去。

形参个数可变的参数是什么?

Jdk1.5 之后,Java允许定义形参个数可变的参数,从而允许为方法指定数量不确定的形参。如果在定义方法时,在最后一个形参的类型后增加三点 (…),则表明该形参可以接受多个参数值,多个参数值被当成数组传入。

代码语言:javascript
复制

public class MyClass {
    private static int age;

    public static void main(String[] args) {
        Demo(2,3,4);
        Demo(new int[]{12,2});
    }

    static void Demo(int... a2) {
        for (int i : a2) {
            System.out.println(i);
        }
    }

}

但需要注意的是,长度可变的形参只能处于形参列表的最后。一个方法最多只能包含一个长度可变的形参。长度可变的形参本质就是一个数组类型的形参,因此调用包含一个长度可变形参的方法时,这个长度可变的形参即可以传入多个参数,也可以传入一个数组。

为什么方法的返回值类型不能用于区重载的方法?

对于 int f()和 void f() 两个方法,如果 int a=f(),系统可以识别是调用返回值类型为 int 的方法;但Java 调用方法时 可以忽略 方法的返回值,如果直接调用 f(),那么谁有知道到底是调用了那个方法呢?

为什么需要添加set get方法?

Java类里实例变量的 set 和get方法有着非常重要意义,例如,某个类里包含了一个名为 abc 的实例变量,则其对应的 set和get 方法名应为setAbc() 和 getAbc(). 如果一个类 Java 类的每个实例 变量都被使用 private 修饰,并为每个实例变量都提供了 public 修饰的 set 和 get方法,那么这个类就是一个 符合 JavaBean 规范的类,因此,JavaBean 总是一个封装良好的类。

一个类常常就是一个小的模块,应该只让这个模块公开必须让外界知道的内容,而隐藏其他的一切内容。进行程序设计时,应尽量避免一个模块直接操作和访问另一个模块的数据,模块设计追求 高内聚(尽可能把模块之间的内部数据,功能实现细节隐藏在模块内部独立完成,不允许外部直接干预),低耦合(仅暴露少量的方法给外部使用)。

构造器创建Java对象的途径,是不是说构造器完全负责 Java对象?

不是,构造器是创建 Java 对象的重要途径,通过 new 关键字调用构造器时,构造器也确实返回了 该类的对象,但这个对象并不是完全由构造器负责创建的。实际上,当程序员调用构造器时,系统会先为该对象分配内存空间,并为这个对象执行默认初始化,这个对象已经产生了——这些操作系统在构造器的执行前就都已经完成了。也就是说,当系统开始执行构造器的执行体之前,系统已经创建了一个对象,只是这个对象还不能被外部程序访问,只能在该构造器中通过this 来引用。当构造器的执行体结束后,这个对象作为构造器的返回值而被返回,通常还会赋给另一个引用类型的变量,从而让外部程序可以访问该对象。

super限定的用处?

如果需要在子类方法中调用 父类被覆盖的实例方法。则可使用 super 限定来调用父类被覆盖的实例方法。

代码语言:javascript
复制
package com.example.javatest;

public  class Demo extends A{
    public static void main(String[] args) {
        new Demo().test();
    }
    public void test(){
        super.test();
        System.out.println("Demo");
    }
}
class  A{
    public void test(){
        System.out.println("A");
    }
}
什么是多态?

Java 引用变量有两个类型,一个是编译型类型,一个是运行时类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给变量的对象决定。如果编译时类型和运行时类型不一样。就可能出现所谓的多态。

当把一个子了i对象那个直接赋给父类引用变量时,运行时调用该引用变量的方法是,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征。

instanceof 运算符是干什么的?

判断是否是可以成功转换 instanceof 运算符的前一个操作数通常是一个 引用类型变量,后一个操组数通常是一个类(也可以是接口,可以把接口理解成一种特殊的类),它用于判断前面的对象是否是后面的类,或者其子类,实现类的实例。如果是,返回 true,否则 返回false

代码语言:javascript
复制
public class Demo {

    public static void main(String[] args) {
        Object a=new String("123");
        if (a instanceof Integer) {
            System.out.println("123");
        }
    }
}
谈谈你对继承的理解?

继承最大的好处就是类的复用性,子类可以直接调用父类的所有成员变量和方法。但是继承带来高度复合的同事,也带来了一个严重的问题:继承严重破坏了父类的封装性。Java 里对封装的定义是:每个类都应该封装它内存信息和实现细节,而只暴露必要的方法给其他类使用。但在继承关系中,子类可以直接访问父类的成员变量(内部信息)和方法,从而造成子类和父类的严重耦合。

所以我们在使用继承的时候。首先得明白:子类是一种能特殊的父类。

对于具备以下条件之一才使用继承,否则使用 组合 也能实现类的复用。

  • 子类需要额外增加属性,而不仅仅是属性值的改变。
  • 子类需要增加自己独有的行为方式(包括增加新的方法或重写父类的方法)
谈谈你对组合的理解?

把一个类当做一个类的组合成分,从而允许新类直接复用该类的 public 方法,这种就是组合。

一般用到组合的地方,用继承也可以实现,简单来说,继承是对已有类的一番改造,以此获得一个特殊的类。简而言之,就是将一个较为抽象的类改造成能适用于某些特定需求的类,比如在原来基础上增加别的成员变量或者方法等。反之,如果两个类之间有明确的整体,部分的关系,此时就应该采用组合关系来实现复用。

总之,继承要表达的是 (is-a)的关系,而组合表达的是 有 (has-a)的关系。(is-a代表的是继承关系,has-a代表的是对象和它成员的从属关系)

什么是自动装箱?

自动装箱,就是可以把一个基本类型变量直接赋给对应包装类变量,或者赋给Object变量,(Object是所有类的父类,自诶对象可以直接符给父类变量),自动拆箱则则与之相反,允许直接·把包装类对象直接赋给一个对应的基本类型变量。

简单讲一下==与 equals 方法有什么不同?

Java程序测试两个变量是否相等有两种方式,一种是利用== 运算符,另一种就是利用 equals方法,当时用 判断两个变量是否相等时,如果两个变量时基本类型变量,且都是数据类型,则只要两个变量的值相等,就将返回 true。但对于引用类型变量,只要他们指向同一个对象, 判断才会返回true,== 不可用与比较类型上没有父子·关系的两个对象。euqals 判断的是引用对象里包含的字符序列是否相同,相同就返回true,

简单讲一下 final 修饰符

final修饰符可用于修饰类,变量和方法。final 修饰的变量度不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值。final修饰的成员变量必须由程序员显示的指定初始值,因为系统不会为 final 修饰的变量隐式初始化。

final修饰基本引用类型和运用类型变量有什么区别?

当时用final 修饰基本类型数据时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。

为什么被final修饰的变量 被称为 执行宏替换 的变量?

当定义final 变量时就为该变量指定了初始值,而且该初始值可以在编译期间确定下来,那么这个 final 变量本质上就是一个 宏变量 ,编译器会把程序中所有用到该变量的地方直接替换为该变量的值。

谈谈你对抽象类与抽象方法的理解?
  1. 抽象类必须是 abstact 修饰符来修饰,抽象方法也必须使用 abstract 修饰符来修饰,抽象方法不能有方法体。
  2. 抽象类·不能被实例化,无法使用 new 关键字来调用 抽象类的构造器创建抽象类的实例。
  3. 抽象类可以包含成员变量,方法(普通方法和抽象方法都可以),构造器,初始化块,内部类(接口,枚举)5种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。
  4. 含有抽象方法的类(包括直接定义了一个抽象方法;或继承了一个抽象方法,但没有完全实现父类包含的抽象方法;或实现了一个接口,但没有完全实现接口包含的抽象方法三种情况)只能被定义成抽象类。

需要注意的是:

  • static 和 abstract 不能同时修饰某个方法。
  • static 和 abstract 可以同时修饰内部类
  • abstract 关键字修饰的方法必须被其子类重写才有意义,否则这个方法将永远不会有方法体。
抽象类的作用是什么?

抽象类不能创建实例,只能当成父类来继承。从语义的角度来说,抽象类是从多个具体类中抽象出来的父类,他具有更高层此的抽象。从多个具有相同特征的类中抽象出了一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性。

抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展,改造,但子类总体上会大致保留抽象类的行为方式。

什么是接口?

在java8里,允许为接口定义默认方法,类方法。

接口从宏观上来说,是从多个相似类中抽象出来的规范,接口不提供任何实现。说简单点,接口反映的是一类事物的方法。

接口里可以包含成员变量(只能是静态常量),方法(只能是抽象实例方法,类方法或默认方法),内部类(内部接口,枚举)

接口支持多继承。

谈谈你对接口和抽象类的理解?

接口和抽象类具有如下相同特征:

  • 接口和抽象类都不能被实例化,他们都位于继承树的顶端,用于被其他类实现和继承。
  • 接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。
  • 但接口和抽象类之间的差别非常大,这种差别主要体现在二者的设计目的上。
  • 接口体现的是一种规范。对于接口的实现者而言,接口规定了实现者必须向外提供哪些服务(以方法的形式提供);对于接口的调用者而言,接口规定了调用者可以调用哪些服务,以及如何调用这些服务(就是如何来调用方法)。当一个程序中使用接口时,接口时多个模块间的耦合标准。 从某种程度上来看,接口类似于整个系统的 总纲 ,它制定了系统各模块应该遵循的标准,因此一个系统中的接口不应该经常改变。一旦接口被改变,对整个系统升值其他系统的影响将是辐射性的,导致系统中大部分类都需要改写。 抽象类作为系统中多个子类的共同父类,它所体现的是一种模板设计。抽象类作为多个子类的抽象父类,可以被当成系统实现过程中的中间产品,这个中间产品已经实现了系统的部分功能(那些已经提供实现的方法),但这个产品依然不能被当成最终产品,必须有跟进异步的完善,这汇总完善可能有几种不同的方式。
  • 在用法上,抽象类和接口也存在如下差别:
    1. 接口里只能包含抽象方法和默认方法,不能为普通方法提供方法实现;抽象类则完全可以包含普通方法。
    2. 接口里不能定义静态方法,抽象类里可以定义静态方法。
    3. 接口里只能定义静态常量,不能定义普通成员变量;抽象类既可以定义普通成员变量,也可以定义静态常量。
    4. 接口i不包含构造器,抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
    5. 接口里不能包含初始化块,但抽象类则完全可以包含初始化块。
    6. 接口可以多实现,抽象类只能单继承。
什么是内部类?

将一个类放在另一个类的内部定义,这个定义在其他类内部的类被称为内部类,包含内部类的类也被称为外部类。

内部类的作用如下:

  • 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。
  • 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节,例如内部类的成员变量。
  • 匿名内部类适合用于创建那些仅需要一次使用的类。

内部类与外部类还与如下区别:

  • 内部类比外部类多使用三个修饰符,pivate ,protected,static 外部类不可以使用这三个修饰符。
  • 非静态内部类不能拥有静态成员。
为什么静态内部的实例方法也不能访问外部类的实例属性?

因为静态内部类是外部类的类相关的,而不是外部类的对象相关的。也就说说,静态内部类对象不是寄生在外部类的实例中,而是寄生在外部类的本身中。当静态内部类对象存在时,并不存在一个被它寄生的外部类对象,静态内部类对象只持有外部类的类引用,没有持有外部类对象访问。如果允许静态内部类的实例方法访问外部类的实例成员,但找不到被寄生的外部类对象,这将引起错误。

Lambda表达式的使用
  • 形参列表.形参列表允许省略形参列表。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。
  • 箭头 (->)
  • 代码块。如果代码块只包含一条语句,lambda 表达式允许省略代码块的花括号。如果Lambda 代码只有一条return语句,那么省略return 关键字。

遍历list 的方式

代码语言:javascript
复制
  List<String> list=new ArrayList<>();
        list.add("123");
        list.add("123");
        list.add("123");
        list.add("123");
        list.add("123");
        list.forEach(System.out::println);

实现Runnable接口

代码语言:javascript
复制
  new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(123);
            }
        }).start();
        
        new Thread(()-> System.out.println("123")).start();

使用匿名内部类

代码语言:javascript
复制
Runnable runnable=new Runnable() {
    @Override
    public void run() {
        System.out.println(123);      
    }
};

Runnable r1=()-> System.out.println("123");
r1.run();

如下写法

代码语言:javascript
复制
public class MyClass {

    public static void main(String[] args) {
            new MyClass().eat(()-> System.out.println("132"));
            new MyClass().fly(weather -> {
                System.out.println("今天");
            });
            new MyClass().test((a,b)->a+b);
    }
    public void eat(Eatable e){
        System.out.println(e);
        e.taste();
    }
    public void fly(Flyable f){
        f.fly("Petterp");
    }
    public void test(Addable a){
        a.add(5,3);
    }
}
interface Eatable{
    void taste();
}

interface Flyable{
    void fly(String weather);
}

interface Addable{
    int add(int a,int b);
}
什么是枚举?

枚举类是一种特殊的类,他一样可以有自己的成员变量,方法,可以实现一个或者多个接口,也可以定义自己的构造器。一个 Java源文件中最多只能定义一个 public 访问权限的枚举类,且该 Java 源文件也必须和枚举类的类名相同。 枚举类与普通类之间有如下区别:

  • 枚举类可以实现一个或多个接口,使用 enum 定义的枚举类默认集成了 java.lang.Enum 类,而不是默认集成 Object 类,因此枚举类不能显示继承其他父类。其中java.lang.Enum类实现了 JAVA.langSerializable 和 java.lang.Comparable两个接口。
  • 使用Enum 定义,非抽象的枚举类默认会使用 final 修饰,因此枚举类不能派生子类。
  • 枚举类的构造器只能使用 private 访问控制符,如果省略了构造器的访问控制符,则默认使用 private修饰,如果强制指定访问控制符,则 只能 指定 private修饰符。
  • 枚举类的所有实例必须在枚举类的第一行显示列出,否则这个枚举类永远都不能产生实例。列出这些实例时,系统会自动添加 public static fianl 修饰。
枚举类的使用:
代码语言:javascript
复制
public enum SeasonEnum {
    a,b,c,d;
    public String name;
}
class Demo{
    public static void main(String[] args) {
        for (SeasonEnum s:SeasonEnum.values()){
            //打印枚举值的索引
            System.out.println(s.ordinal());
        }
        //如果该枚举对象位于指定枚举对象之后,则返回正整数;
        //如果该枚举对象位于指定枚举对象之前,则返回负整数,否则返回0
        System.out.println(SeasonEnum.valueOf("a").compareTo(SeasonEnum.valueOf("b")));

        //创建枚举类对象
        SeasonEnum seasonEnum=Enum.valueOf(SeasonEnum.class,"a");
        seasonEnum.name="Petterp";
        System.out.println(seasonEnum.name);
    }
}

枚举类也可以用于 switch

枚举类带构造器的使用

代码语言:javascript
复制
public enum SeasonEnum {
    //此处的枚举值必须调用对应的构造器来创建
    MALE("男"), FEmale("女");
    private final String name;

    //枚举类的构造器只能使用private修饰
     SeasonEnum(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Demo {
    public static void main(String[] args) {
        System.out.println(SeasonEnum.FEmale);
    }
}

以上代码如同于以下代码

代码语言:javascript
复制
public  static  final SeasonEnum MALE=new SeasonEnum("男");
public  static  final SeasonEnum FEmale=new SeasonEnum("女");

在枚举类中列出枚举值是,实际上就是调用构造器创建枚举类对象,只是这里无须使用new 关键字,也无需显示调用构造器。前面列出枚举值是无须传入参数,甚至无须使用括号,仅仅是因为前面的枚举类包含无参数的构造器。

实现接口的枚举类

枚举类也可以实现一个或多个接口,与普通类实现一个或多个接口完全一样,枚举类实现一个或多个接口时,也需要实现该接口所包含的方法。

代码语言:javascript
复制
public enum SeasonEnum implements Port {
    //此处的枚举值必须调用对应的构造器来创建
    MALE("男") {
        @Override
        public void info() {
            System.out.println("这个枚举值代表男性");
        }
    },
    FEmale("女") {
        @Override
        public void info() {
            System.out.println("这个枚举值代表女性");
        }
    };
    private final String name;

    //枚举类的构造器只能使用private修饰
    SeasonEnum(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Demo {
    public static void main(String[] args) {
       SeasonEnum.FEmale.info();
    }
}

 

上面的代码看起来有些奇怪,当创建 MALE 和 FEMALE 两个枚举值时,后面又紧跟了一对花括号,这队花括号包含了一个 info 方法定义。花括号部分实际上就是一个类体部分,在这种情况下,当创建 MALE,FEMALE 枚举值是,并不是直接创建 SeasonEnum枚举类的实例,而是相当于创建 SeasonEnum的匿名子类的实例。因为粗体字括号部分实际上是匿名内部类的类体部分,所以这个部分的代码语法与匿名内部类语法大致相似,只是它依然是枚举类的匿名内部类。

枚举类不是用 final 修饰吗,为什么还可以派生子类?

并不是所有的枚举类都是用了 final 修饰,非抽象的枚举类才默认使用 final 修饰,对于一个抽象的枚举类而言,只要它包含了抽象方法,它就是抽象枚举类,系统会默认是使用 abstart修饰。

枚举类可以包含抽象方法吗?
代码语言:javascript
复制
public enum Operation {
    Plus {
        @Override
        public double eval(double x, double y) {
            return 0;
        }
    },
    MINUS{
      public double eval(double x,double y){
          return x-y;
      }
    };
    //为枚举类定义一个抽象方法
    //这个抽象方法由不同的枚举值提供不同的实现
    public abstract  double eval(double x,double y);

    public static void main(String[] args) {
        System.out.println(Operation.Plus.eval(3,4));
    }
    
    //枚举类里定义抽象方法是不能使用 abstart 关键字将枚举类定义成抽象类(因为系统自动会为它添加 abstart 关键字),但因为枚举类需要显示创建枚举值而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对象的this引用是什么?
  • 为什么static成员不能直接访问非静态成员?
  • 为什么同一类里,静态和非静态方法可以相互调用?
  • Java的参数传递中可以引用传递吗?
  • 形参个数可变的参数是什么?
  • 为什么方法的返回值类型不能用于区重载的方法?
  • 为什么需要添加set get方法?
  • 构造器创建Java对象的途径,是不是说构造器完全负责 Java对象?
  • super限定的用处?
  • 什么是多态?
  • instanceof 运算符是干什么的?
  • 谈谈你对继承的理解?
  • 谈谈你对组合的理解?
  • 什么是自动装箱?
  • 简单讲一下==与 equals 方法有什么不同?
  • 简单讲一下 final 修饰符
  • final修饰基本引用类型和运用类型变量有什么区别?
  • 为什么被final修饰的变量 被称为 执行宏替换 的变量?
  • 谈谈你对抽象类与抽象方法的理解?
  • 抽象类的作用是什么?
  • 什么是接口?
  • 谈谈你对接口和抽象类的理解?
  • 什么是内部类?
  • 为什么静态内部的实例方法也不能访问外部类的实例属性?
  • Lambda表达式的使用
  • 什么是枚举?
    • 枚举类的使用:
      • 实现接口的枚举类
        • 枚举类不是用 final 修饰吗,为什么还可以派生子类?
          • 枚举类可以包含抽象方法吗?
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档