作者简介: zoro-1,目前大一,正在学习Java,数据结构等
作者主页: zoro-1的主页
欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖💖
内部类
实例内部类
实例内部类是嵌套在一个类的非静态成员位置上的类 ,它可以访问外部类的实例变量和方法。
以下是一个实例内部类的例子:
java
public class OuterClass {
private int x = 10;
public void outerMethod() {
InnerClass inner = new InnerClass();
inner.innerMethod();
}
public class InnerClass {
public void innerMethod() {
System.out.println("x = " + x);
}
}
}
以上代码定义了一个OuterClass类和一个InnerClass类。InnerClass是一个实例内部类,它可以访问OuterClass类中的实例变量x。
在outerMethod()方法中,我们创建了InnerClass的一个实例inner,并调用了它的innerMethod()方法。
在innerMethod()方法中,我们可以看到访问了OuterClass类的实例变量x。
可以使用以下代码在其他类中实例化OuterClass的实例和InnerClass的实例,并访问innerMethod()方法:
java
public class OtherClass {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.outerMethod();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.innerMethod();
}
}
在main()方法中,我们首先实例化了OuterClass的实例outer,并调用了outerMethod()方法。
接着,我们使用outer实例来实例化InnerClass的实例inner,并调用了innerMethod()方法。这两种方式展示了如何使用实例内部类。
注意事项
1.实例内部类中不能定义static修饰的变量
既然是非静态的内部类了,说明这个类只使用于包含它的那个类,专用的。 为什么还要在它里面定义静态的呢原因简单解释一下:把外边的类叫做OutClass,内部类叫做InnerClass,首先要了解JAVA的装载过程,先加载类,然后初始化静态的东西,并且JAVA编译器必须保证所有的静态都在使用前分配好内存空间,然后非静态的只有在使用的时候才分配内存空间。 所以非静态的InnerClass必须得要OutClass实例化之后才会存在,所以非静态InnerClass的静态成员在开始的时候并没有得到初始化(因为这些内存是无法通过任何方式访问的),这就和JAVA的编译原则相违背了。按照上面的讲如果InnerClass为OutClass的静态成员,就可以在它里面定义静态的了,如果非想用static修饰要加上final,那他就是一个常量。
2.实例内部类实例过程
需要先实例外部类,通过外部类对象引用实例
java
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
3.两个this
在Java中,内部类可以访问外部类的成员,包括私有成员。当内部类和外部类的成员重名时,需要使用this关键字来区分。
如果在实例内部类中使用this关键字,this代表的是该内部类的对象。如果同时在内部类和外部类中都使用了this关键字,那么需要使用外部类的类名来限定外部类的this。
下面是一个示例代码:
csharp
public class Outer {
private int num = 10;
public void outerMethod() {
Inner inner = new Inner();
inner.innerMethod();
}
class Inner {
private int num = 20;
public void innerMethod() {
int num = 30;
System.out.println(num); // 30
System.out.println(this.num); // 20
System.out.println(Outer.this.num); // 10
}
}
}
在上面的代码中,Outer类中有一个num成员变量,Inner类中也有一个num成员变量,innerMethod()方法中还有一个局部变量num。
当使用num时,会按照就近原则选择变量,因此输出的是局部变量num的值30。
当使用this.num时,代表的是该内部类的对象,因此输出的是内部类中的num成员变量的值20。
当使用Outer.this.num时,限定了是外部类的this,因此输出的是外部类中的num成员变量的值10。
静态内部类
静态内部类是指在外部类的内部定义的类,使用static修饰符修饰。静态内部类与非静态内部类不同,它可以直接被外部类所引用,而不需要先实例化外部类。静态内部类可以访问外部类的静态属性和方法,但不能直接访问外部类的非静态属性和方法,需要通过实例化外部类才能访问。
静态内部类的语法格式与非静态内部类类似,只不过多了一个static修饰符。例如:
java
class Outer {
private static int x = 10;
private int y = 20;
public static class Inner {
public void print() {
System.out.println("x = " + x); // 可以访问外部类的静态属性
//System.out.println("y = " + y); // 不可以访问外部类的非静态属性
}
}
}
可以看到,在静态内部类中可以直接访问外部类的静态属性x ,但不能访问外部类的非静态属性y。要想访问y,需要通过实例化外部类对象进行访问。例如:
java
Outer outer = new Outer();
Outer.Inner inner = new Outer.Inner();
System.out.println("y = " + outer.y); // 可以通过实例化外部类对象访问非静态属性
inner.print();
注意事项
1.静态内部类实例化过程
不需要实例化外部类直接用外部类类名调用
java
Outer.Inner inner = new Outer.Inner();
2.静态内部类访问外部类变量
只能调用static修饰的,访问外部类的非静态,需要通过实例化外部类对象进行访问
3.外部类访问静态内部类变量
外部类访问静态内部类可以直接使用内部类的名称。由于静态内部类可以直接被外部类所引用,因此可以不用创建内部类的对象就直接访问其静态属性和方法。例如:
java
class Outer {
private static int x = 10;
public static class Inner {
public static int y = 20;
public static void print() {
System.out.println("x = " + x); // 可以访问外部类的静态属性
}
}
}
class Test {
public static void main(String[] args) {
System.out.println(Outer.Inner.y); // 直接访问内部类的静态属性
Outer.Inner.print(); // 直接调用内部类的静态方法
}
}
在外部类中直接访问静态内部类的静态属性和方法,无需通过内部类的对象进行访问。需要注意的是,在静态内部类中可以直接访问外部类的静态属性,但不能访问外部类的非静态属性。
局部内部类(不常用)
局部内部类是定义在方法或代码块内部的内部类。它们只能在该方法或代码块内访问,并不能在其它方法或类中使用。局部内部类通常用于解决某些特定问题,例如实现某个接口或抽象类,或者作为某个方法的返回值。
局部内部类的语法格式如下:
java
public class OuterClass {
public void someMethod() {
class LocalInnerClass {
// 内部类的定义
}
// 创建局部内部类的对象
LocalInnerClass inner = new LocalInnerClass();
}
}
在上面的示例中,我们定义了一个名为 LocalInnerClass
的局部内部类,并在外部方法中创建了它的对象。
需要注意的是,局部内部类可以访问外部方法的局部变量,但需要将它们声明为 final
类型。这是因为,当方法执行完毕后,局部变量就会被销毁,而内部类对象可能仍然存在,如果内部类对象仍然能够访问这些已被销毁的变量,就会引发问题。因此,将变量声明为 final
类型,就能够确保内部类对象只能够访问它们的值,而不能够修改它们。
匿名内部类
匿名内部类是一种没有名称的内部类,它可以在创建对象的同时定义类的实现。通常用于创建简单的、只使用一次的类实例,同时避免创建新的文件来定义这个类。通常我们会将匿名内部类作为参数传递给其他方法或作为表达式在代码中使用。例如:
java
Button button = new Button("Click Me");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked");
}
});
在这个例子中,我们创建了一个按钮实例,然后通过addActionListener()
方法添加了一个匿名内部类作为其事件监听器。这个内部类实现了ActionListener
接口,并在其中定义了按钮点击时的操作。
匿名内部类有以下特点:
- 没有名称:无法在其他地方使用这个类。
- 继承或实现:必须继承一个类或实现一个接口。
- 单例:每次创建匿名内部类实例时都会创建一个新的对象,因此通常只使用一次。
- 作用域:只能在定义它的方法或代码块内使用。
今天的分享到这里就结束了,感谢大家支持,创作不易,希望大家能给博主个三连