1.内部类
内部类就是在一个类中定义另一个类,这个类中被定义的类就叫做内部类
内部类定义格式
public class 类名{
修饰符 class 内部类名{
成员...
}
}
代码中的体现
public class Outer {
private String strOuter= "这是外部类中的私有成员变量";
public void OuterMethod(){
System.out.println("这是外部类中的公有成员函数");
}
//定义内部类
public class Inner{
private String strInner = "这是内部类中的私有成员变量";
public void InnerMethod(){
System.out.println("这是内部类中的私有成员方法");
}
}
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println(outer.strOuter);
outer.OuterMethod();
}
}
这段代码定义了一个外部类Outer和一个内部类Inner。
在外部类Outer中,定义了一个私有成员变量strOuter和一个公有成员函数OuterMethod。strOuter是外部类中的私有成员变量,只能在外部类中直接访问。OuterMethod是外部类中的公有成员函数,可以在外部类和外部类的对象中访问和调用。
内部类Inner是定义在外部类Outer中的,可以直接访问外部类的成员变量和方法。内部类Inner的定义和普通类一样,它有一个私有成员变量strInner和一个公有成员函数InnerMethod。
在main函数中,首先创建了一个Outer类的对象outer,然后通过outer对象访问了外部类的私有成员变量strOuter和公有成员函数OuterMethod。
要访问内部类Inner的成员变量和方法,需要创建内部类的对象。由于内部类是非静态的,所以需要通过外部类的对象来创建内部类的对象。这段代码没有创建内部类Inner的对象,所以没有访问内部类的成员变量和方法。
那么接下来,我们想办法调用一下内部类,可以这么做:
public class Outer {
private String strOuter= "这是外部类中的私有成员变量";
public void OuterMethod(){
System.out.println("这是外部类中的公有成员函数");
}
//定义内部类
public class Inner{
private String strInner = "这是内部类中的私有成员变量";
public void InnerMethod(){
System.out.println("这是内部类中的私有成员方法");
}
}
public void runInner(){
Inner inner = new Inner();
System.out.println(inner.strInner);
inner.InnerMethod();
}
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println(outer.strOuter);
outer.OuterMethod();
//通过外部类调用runInner方法
outer.runInner();
}
}
在Outer
类中定义了一个名为runInner
的方法,该方法在其内部创建了一个Inner
对象inner
,并使用inner.strInner
和inner.InnerMethod()
来访问内部类的成员变量和方法。
最后,我们通过outer.runInner()
来调用runInner
方法,间接地通过外部类对象来访问内部类的成员变量和方法。
还可以使用多重调用关系,创建一个内部类对象来调用内部类
public class Outer {
private String strOuter= "这是外部类中的私有成员变量";
public void OuterMethod(){
System.out.println("这是外部类中的公有成员函数");
}
//定义内部类
public class Inner{
private String strInner = "这是内部类中的私有成员变量";
public void InnerMethod(){
System.out.println("这是内部类中的私有成员方法");
}
}
public void runInner(){
Inner inner = new Inner();
System.out.println(inner.strInner);
inner.InnerMethod();
}
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println(outer.strOuter);
outer.OuterMethod();
//通过外部类调用runInner方法
outer.runInner();
//多重调用,创建内部类对象
Inner inner = outer.new Inner();
System.out.println(inner.strInner);
inner.InnerMethod();
}
}
2.成员内部类
成员内部类是定义在外部类中的类,它与外部类的其他成员变量和方法具有相同的访问权限(public、protected、default和private)。
成员内部类可以访问外部类的私有成员变量和方法,包括静态和非静态的。同时,外部类也可以通过实例化内部类对象来访问内部类的成员变量和方法。
代码中的体现
public class Outer {
private String strOuter= "这是外部类中的私有成员变量";
public void OuterMethod(){
System.out.println("这是外部类中的公有成员函数");
Inner inner = new Inner();
inner.show();
inner.InnerMethod();
}
//定义内部类
public class Inner{
public void show(){
System.out.println(strOuter);
}
private String strInner = "这是内部类中的私有成员变量";
public void InnerMethod(){
System.out.println("这是内部类中的私有成员方法");
}
}
}
这段代码定义了一个成员内部类Inner
,并在外部类Outer
的方法OuterMethod()
中实例化了内部类对象,并调用了内部类的方法。
在OuterMethod()
方法中,我们创建了一个内部类对象inner
,然后通过inner.show()
方法打印了外部类的私有成员变量strOuter
的值。内部类可以直接访问外部类的私有成员变量。
接着,我们调用了内部类的InnerMethod()
方法,打印了一条信息。
这段代码展示了成员内部类可以访问外部类的私有成员变量和方法,并且通过外部类对象来实例化和调用内部类对象。
public class Ts {
public static void main(String[] args) {
//间接访问
Outer outer = new Outer();
outer.OuterMethod();
//直接访问
Outer.Inner inner = outer.new Inner();
inner.show();
inner.InnerMethod();
}
}
这段代码演示了如何通过间接访问和直接访问来访问内部类。
在main
方法中,我们首先创建了外部类对象outer
,然后通过该对象调用了外部类的成员函数OuterMethod()
。这是一种间接访问内部类的方式,因为我们在外部类的方法中实例化了内部类对象,并调用了内部类的方法。
接下来,我们使用直接访问方式来访问内部类。首先,我们通过outer.new Inner()
创建了内部类对象inner
,然后通过该对象调用了内部类的方法show()
和InnerMethod()
。这是一种直接访问内部类的方式,因为我们直接通过外部类对象来实例化和调用内部类对象。
无论是间接访问还是直接访问,我们都能够访问内部类的成员变量和方法。
3.局部内部类
局部内部类是定义在方法内部的内部类。与成员内部类不同,局部内部类只在所属方法中可见,对于其他方法和类来说是不可见的。
局部内部类的特点:
- 只能在所属方法中被使用,无法在外部方法或其他类中使用。
- 局部内部类可以访问外部方法的局部变量和参数(final 和 effectively final 变量)。
- 局部内部类不能定义静态成员(static 成员)。
- 局部内部类可以访问外部类的所有成员,包括私有成员。
代码中的体现
public class Outer {
private String strOuter = "外部类成员变量";
public void outerMethod(){
//局部内部类不加修饰符
class Inner{
public void show(){
System.out.println(strOuter);
}
public void InnerMethod(){
System.out.println("内部类的成员方法");
}
}
Inner inner = new Inner();
inner.show();
inner.InnerMethod();
}
}
这段代码定义了一个外部类 Outer
,其中包含一个方法 outerMethod
。在 outerMethod
方法中,定义了一个局部内部类 Inner
。
Inner
类是在 outerMethod
方法内部定义的,所以它只能在 outerMethod
方法内部使用。它具有两个成员方法:show
和 InnerMethod
。
在 outerMethod
方法中,我们创建了 Inner
类的实例 inner
,并调用了它的 show
和 InnerMethod
方法。在 show
方法中,我们访问了外部类的成员变量 strOuter
。
public class Ts {
public static void main(String[] args) {
Outer outer = new Outer();
outer.outerMethod();
}
}
直接通过外部类对象来调用
4.匿名内部类
匿名内部类是一种没有名字的类,在定义的同时实例化并使用。它通常用于简化代码,特别是在需要实现某个接口或继承某个类的情况下。
匿名内部类的语法和普通类定义相似,但是没有类名。它可以直接在方法中定义,也可以作为方法参数或返回值使用。它的定义通常包含在一个方法中,并且在方法中创建并使用
1.代码中的体现
public abstract class Inner {
public abstract void show();
}
这段代码定义了一个抽象类Inner
,具有一个抽象方法show
。抽象类是不能直接实例化的,需要通过继承它的子类来创建实例。
在这个代码中,Inner
类是一个抽象类,它包含了一个抽象方法show
。抽象方法是没有具体实现的方法,子类必须实现这个方法。这是一种约束,确保子类都有相同的方法。
代码中的show
方法定义了一个抽象方法,没有具体的实现。子类必须重写这个方法来提供具体的实现。
使用这个抽象类,需要创建一个继承它的子类,并实现show
方法。例如:
public class InnerExts extends Inner{
@Override
public void show() {
System.out.println("这是Inner子类中的show方法");
}
}
这段代码定义了一个名为InnerExts
的类,它继承了抽象类Inner
。InnerExts
类必须实现继承自Inner
抽象类的抽象方法show
。
在InnerExts
类中,重写了show
方法,提供了具体的实现。在这个例子中,show
方法会打印出"这是Inner子类中的show方法"。
public class Outer {
public void OuterMethod(){
new Inner() {
@Override
public void show() {
System.out.println("这是匿名内部类");
}
}.show();
}
}
这段代码定义了一个名为Outer
的类,其中包含了一个方法OuterMethod
。
在OuterMethod
方法中,创建了一个匿名内部类。匿名内部类是一种没有显式声明类的特殊类型的类。它直接在代码中定义,并且通常用于只需要临时使用一次的情况下。
在这个例子中,匿名内部类实现了抽象类Inner
的show
方法,并提供了具体的实现。在匿名内部类的show
方法中,打印出"这是匿名内部类"。
通过创建匿名内部类的实例并调用其中的方法,可以执行匿名内部类的具体实现。
public class Ts {
public static void main(String[] args) {
new Outer().OuterMethod();
new InnerExts().show();
new Inner() {
@Override
public void show() {
System.out.println("主方法中直接使用匿名内部类");
}
}.show();
}
}
这段代码定义了一个名为Ts
的类,其中包含了一个main
方法。
在main
方法中,分别创建了三个对象并调用了它们的show
方法。
-
new Outer().OuterMethod()
:创建一个Outer
对象,并调用其中的OuterMethod
方法。在OuterMethod
方法中,创建了一个匿名内部类并调用了它的show
方法,输出结果为"这是匿名内部类"。 -
new InnerExts().show()
:创建一个InnerExts
对象,并调用其中的show
方法。InnerExts
是Inner
的子类,它重写了show
方法,并输出结果为"这是Inner子类中的show方法"。 -
new Inner() { ... }.show()
:创建一个匿名内部类,并调用其中的show
方法。在匿名内部类中重新实现了show
方法,并输出结果为"主方法中直接使用"。
因此,最终输出的结果是:
这是匿名内部类
这是Inner子类中的show方法
主方法中直接使用
这段代码展示了在不同的场景中使用匿名内部类的方法。可以在方法内部直接创建匿名内部类并调用其中的方法。
2.匿名内部类的使用案例
public interface Run {
void run();
}
这段代码定义了一个名为Run
的接口,其中包含了一个抽象方法run
。
接口是一种抽象的数据类型,它定义了一组方法的签名,但没有具体的实现。接口可以被其他类实现,实现类需要提供具体的方法实现。
在这个接口中,只定义了一个run
方法,该方法没有任何参数和返回值。实现该接口的类需要提供自己的run
方法的具体实现。
这个接口可以用来表示某个对象可以执行运行的操作。实现该接口的类需要重写run
方法,并在方法体中定义运行的具体逻辑。
public class Dog implements Run{
@Override
public void run() {
System.out.println("狗叼着骨头跑");
}
}
这段代码定义了一个名为Dog
的类,该类实现了Run
接口。
通过implements
关键字,Dog
类表示它将实现Run
接口中定义的方法。
在Dog
类中,重写了run
方法,即提供了run
方法的具体实现。在方法体中,输出了"狗叼着骨头跑"。
通过实现Run
接口,Dog
类可以被视为一个可以执行运行操作的对象。其他代码可以通过调用run
方法来让Dog
对象执行运行操作。
public class whoRun {
public void show(Run r){
r.run();
}
}
这段代码定义了一个名为whoRun
的类,其中包含一个名为show
的方法。
show
方法的参数是一个Run
接口类型的对象r
,表示可以接受任何实现了Run
接口的对象。
在show
方法内部,通过调用r.run()
来执行传入对象的run
方法。
通过这个show
方法,可以将任何实现了Run
接口的对象作为参数传入,并调用其run
方法进行运行操作。这种设计方式实现了多态,提高了代码的灵活性和可扩展性。
public class Ts {
public static void main(String[] args) {
whoRun whoRun = new whoRun();
Dog dog = new Dog();
//使用多态的方式
whoRun.show(dog);
//使用匿名内部类
whoRun.show(new Run() {
@Override
public void run() {
System.out.println("猫叼着鱼跑");
}
});
//使用Lambda函数
whoRun.show(() -> System.out.println("猫叼着鱼跑"));
}
}
这段代码定义了一个名为Ts
的类,其中包含一个main
方法。
在main
方法中,首先创建了一个whoRun
对象和一个Dog
对象。
接着,通过多态的方式,调用whoRun
对象的show
方法,将Dog
对象作为参数传入。由于Dog
类实现了Run
接口,并重写了run
方法,所以在show
方法内部会调用Dog
对象的run
方法,输出"狗叼着骨头跑"。
接下来,使用匿名内部类的方式,创建了一个实现Run
接口的匿名类对象,并重写了run
方法,在run
方法中输出"猫叼着鱼跑"。再次调用whoRun
对象的show
方法,将匿名类对象作为参数传入,会执行匿名类对象的run
方法,输出"猫叼着鱼跑"。
最后,使用Lambda表达式的方式,创建了一个函数式接口Run
的实现对象,实现了run
方法,并在run
方法中输出"猫叼着鱼跑"。再次调用whoRun
对象的show
方法,将Lambda表达式作为参数传入,会执行Lambda表达式的run
方法,输出"猫叼着鱼跑"。
通过这段代码,演示了不同方式创建和使用实现了同一个接口的对象,并调用其方法实现不同的功能。这种灵活使用接口和多态的方式,增加了代码的可扩展性和复用性。