JAVA基础——特殊的类和方法(抽象类,抽象方法,内部类 )

本文详细介绍了Java中的抽象类、抽象方法及其使用规则,包括不能实例化抽象类、抽象方法的声明与实现。此外,还探讨了内部类的四种类型——成员内部类、局部内部类、匿名内部类和静态内部类,以及它们的特点和应用场景,强调了内部类在解决多继承问题中的重要作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


Java中,有一些特殊的方法和类。

抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
类和类之间有共同的特征,将这些特征进一步提取出来,就形成了抽象类。
在Java语言中使用abstract class来定义抽象类。其语法结构为:
修饰符 abstract class 类名{
…………
}
抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
抽象类虽然不能实例化对象,但是抽象类里面有属性,方法和构造方法,这些方法是供继承抽象类的子类使用的。
如:

public abstract class Test {
    int c;
    public Test() {
        c = 0;
    }
    public Test(int a){
        c = a;
    }
    public int method(int a){
        return a;
    }
}

定义了一个类名为Test的抽象类,里面有属性c,有有参数的和无参数的构造方法,有返回值为int的方法。这些属性和方法不是Test类自己用的,Test类无法创建对象,这些属性和方法是给继承抽象类的子类使用的。
抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

抽象方法

如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。
abstract 关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。方法名后面直接跟一个分号,而不是花括号。
抽象方法的语法结构为:
修饰符 abstract 返回值类型 方法名(参数);
如:

public abstract class Test {
    public abstract void method();
}

在Test抽象类中,定义了一个返回值为void的method抽象方法。
注意,抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

内部类

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。其中匿名内部类使用的较多。

成员内部类

成员内部类是最普通的内部类,它定义与类的内部,如:

public class TestOne{
    int a;
    private int b;
    public class TestTwo{    //成员内部类
        public void method(){
            System.out.println(a+b);
        }
    }
}

在TestOne中定义了一个TestTwo内部类。因为TestTwo就像类中的一个成员,所以我们称它为成员内部类。TestOne称为外部类。
成员内部类可以访问外部类中的所有属性和方法,包括被private修饰的方法和属性。也可以访问外部类中的静态方法和属性。
注意,在成员内部类中,当成员内部类中的成员或方法和外部类中的成员或方法名字相同时,会发生隐藏现象。即默认情况下访问的是成员内部类中的属性或方法,要想访问外部类中的成员或方法,需要用一下方式进行访问:

外部类.this.属性
外部类.this.方法

如果外部类想要访问成员内部类中的成员,必须先创建一个成员内部类的对象,再通过引用进行访问。

public class TestOne{
    int a;
    private int b;
    public class TestTwo{
        public void method(){
            System.out.println(a+b);
        }
    }
    public void testMethod(){
        TestTwo testTwo = new TestTwo();//创建成员内部类对象
        testTwo.method();//通过引用调用成员内部类的method方法
    }
}

想要调用成员内部类中的method方法,必须先创建成员内部类的对象。然后通过引用来访问方法。
如何创建成员内部类对象:

public class Test {
    public static void main(String[] args) {
        TestOne testOne = new TestOne();//先创建外部类对象
        TestOne.TestTwo testTwo = testOne.new TestTwo();//通过外部类对象引用来创建内部类对象
    }
}

需要先创建外部类对象,通过外部类对象来创建内部类对象。
成员内部类和外部类不同,成员内部类可以跟成员一样被public,protect,private,default(默认,即什么也不写)修饰,但外部类只能被public 和default修饰。

局部内部类

局部内部类与成员内部类不同,局部内部类定义于外部类中的方法或者作用域当中,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
如:

public class TestOne {
    int a;
    public void method(){
        class TestTwo{   //局部内部类
            int b;
        }
    }
}

在外部类TestOne的method方法中,定义了局部内部类TestTwo。
注意局部内部类跟方法中的局部变量一样,不能被修饰符修饰。

匿名内部类

匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类。
当一个接口或者一个类需要实现或者继承时,可以使用匿名内部类。直接new + 接口名(父类名)+ (参数,没有参数可以不写) {
……………………
};
注意结束时要加;
如:

public class Test {
    public static void main(String[] args) {
        Animal cat = new Animal("cat"){    //使用匿名内部类,相当于一个继承Animal的cat类

            @Override           //方法重写
            void nameOut() {
                System.out.println("匿名内部类");
                super.nameOut();
            }
        };   //不要忘记以分号结束
        cat.nameOut();
    }
}
class Animal{    //定义一个animal类
    String name;

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

    void nameOut(){
        System.out.println(name);
    }
}

使用匿名内部类,实现了Cat类继承Animal类。如果不使用匿名内部类,我们需要单独写一个继承于Animal的Cat类,可以看出匿名内部类帮我们简化了很多代码。
输出结果如下:
输出结果

注意,匿名内部类是唯一一种没有构造方法的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,匿名内部类只能使用一次,大部分匿名内部类用于接口回调。不要刻意使用匿名内部类,虽然简化了代码,会使程序的可读性变得非常差。

静态内部类

静态内部类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,并且它不能使用外部类的非static成员变量或者方法,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
如:

public class TestOne{
    int a;
    static int b;
    static class TestTwo{  //静态内部类
        int c = b;
    }
}

在外部类TestOne中定义了静态内部类TestTwo,TestTwo只能访问静态变量b,无法访问实例变量a。
静态内部类如何创建对象:

TestOne testOne = new TestOne();
TestOne.TestTwo = new TestOne.TestTwo();

为什么使用内部类

我觉得最重要的一点是,Java中,类和类之间不能多继承,单继承。内部类的存在,使得每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CHB爱Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值