Java 内部类整理(静态内部类、成员内部类、局部内部类、匿名内部类)
一、内部类:
在Java中,将一个类的定义放在另一个类的定义内部,这就是内部类。内部类本身就是一个类的属性
。
举个栗子:
public class Outer {
private int i = 1;
private static int k = 2;
public Outer(){
}
// 定义内部类
class inner{
public void visitOuter(){
System.out.println("visit"+i);
System.out.println("visit"+k);
}
}
}
二、内部类种类:
内部类总共可以分为四种:成员内部类、局部内部类、匿名内部类、静态内部类;
静态内部类:
定义在类内部的静态类
,就是静态内部类;
举个栗子:
public class Outer {
private int i = 1;
private static int k = 2;
public static void outer_f1(){
// 外部静态方法
}
public void outer_f2(){
// 外部方法
}
static class StaticInner{
static int inner_i = 3;
int inner_j = 4;
static void inner_f1(){
System.out.println();
outer_f1();
// outer_f2(); 报错
}
public void visit(){
// System.out.println("visit"+i); 报错
System.out.println("visit"+k);
}
static public void static_visit(){
}
}
// 外部类访问内部类静态成员
public void outer_f3(){
// 外部类访问静态内部类【静态成员|方法 内部类.静态成员|方法】
System.out.println(StaticInner.inner_i);
StaticInner.static_visit();
// 外部类访问静态内部类【非静态成员|方法】 实例化内部类即可
StaticInner staticInner = new StaticInner();
int inner_j = staticInner.inner_j;
staticInner.visit();
}
}
静态内部类创建方式:
public static void main(String[] args) {
Outer.StaticInner staticInner = new Outer.StaticInner();
staticInner.visit();
}
总结:
- 创建方式:new 外部类.静态内部类();
- 静态内部类
可以访问
外部类所有的静态变量|方法,而不可以访问
外部类的非静态变量|方法; - 静态内部类,可以用public、protected、private修饰;
- 静态内部类,可以定义静态变量|方法,也可以定义非静态变量|方法;
- 外部类可以访问内部类静态成员、方法😭
内部类.静态成员|方法
) - 外部类可以访问内部类非静态成员、方法😭
需要先实例化内部类
)
成员内部类:
定义在类内部,成员位置上的非静态类
,就是成员内部类;
举个栗子:
public class Outer {
private int i = 1;
private static int k = 2;
public static void outer_f1(){
}
public void outer_f2(){
}
class Inner{
// static int inner_i = 3; 报错 内部类中不允许定义静态变量
int i = 3; // 内部类中外部类的实例变量可以共存
int inner_j = 4;
void inner_f1(){
System.out.println(k); // 外部类变量与内部类变量没有同名,可以直接用变量名访问外部类变量
System.out.println(i); // 内部类中访问自己的变量直接用变量名
System.out.println(this.i); // 访问外部类与内部类重名的成员变量 this.变量名
}
public void visit(){
// System.out.println("visit"+i); 报错
System.out.println("visit"+k);
}
}
// 外部类非静态方法访问成员内部类
public void outer_f3(){
Inner inner = new Inner();
inner.inner_f1();
}
// 外部类静态方法访问成员内部类
public static void outer_f4(){
// 1.建立外部类对象
Outer outer = new Outer();
// 2.根据外部类对象建立内部类对象
Inner inner = outer.new Inner();
// 3.访问内部类的方法
inner.visit();
}
}
成员内部类创建方式:
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.inner_f1();
}
总结:
-
创建方式:外部类实例.new 内部类();
-
成员内部类,可以访问外部类所有变量|方法(包括静态|非静态、私有|公有);
-
成员内部类中,不允许定义 静态变量|方法;
-
成员内部类,允许定义与外部类变量相同;
-
成员内部类中,访问外部类与内部类重名的成员变量可使用外部类.this.变量名;
-
外部类
非静态方法
访问成员内部类(new 成员内部类); -
外部类
静态方法
访问成员内部类:// 外部类静态方法访问成员内部类 public static void outer_f4(){ // 1.建立外部类对象 Outer outer = new Outer(); // 2.根据外部类对象建立内部类对象 Inner inner = outer.new Inner(); // 3.访问内部类的方法 inner.visit(); }
优点:
- 用内部类定义在外部类中不可访问的属性。这样在外部类中实现了比外部类的private还要小的访问权限;
注意:
- 内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。一个名为outer的外部类和内部名为inner的内部类。
编译完成后出现outer.class 和 outer$inner.class
两个类;
局部内部类:
定义在方法中的内部类,就是局部内部类;
public class Outer {
private int i = 1;
private static int k = 2;
public void func(int q){
final int i = 3;
final int z = 4;
// 定义在方法内部, 局部内部类
class Inner{
int i = 300; // 可以定义与外部类同名的变量
// static int m = 30; 报错, 不可以定义静态变量
// 创建构造方法
Inner(int k){
}
int inner = 100;
void inner_f(int f){
System.out.println(k); // 内部类没有与外部类同名的变量, 可在内部类直接访问外部类实例变量
System.out.println(this.i); // 内部类与外部类变量名相同, 访问内部变量 this.内部变量
System.out.println(Outer.this.i); // 变量名相同, 访问外部类变量 外部类类名.this.变量名
}
}
// 创建局部内部类
Inner inner = new Inner(k);
inner.inner_f(100);
}
public static void static_func(int y){
int d = 3;
class Inner{
private void func(){
// System.out.println(i); 编译错误, 定义在静态方法中的局部类不可以访问外部类的实力变量
System.out.println(k);
}
}
Inner inner = new Inner();
inner.func();
}
}
局部内部类创建方式:
public void func(int q){
class Inner{
}
// 创建局部内部类
Inner inner = new Inner(k);
inner.inner_f(100);
}
总结:
- 局部内部类创建方式,与上述都不同,应在对应方法内,new 内部类();
- 定义在实例方法中的局部类,可以访问到外部类所有变量|方法;
- 定义在静态方法中的局部类,只能访问外部的静态变量|方法;
- 局部内部类与外部类定义变量重名时,访问外部类变量(外部类.this.变量名);
匿名内部类:
匿名内部类就是没有名字的内部类(出现比较频繁);
public class Outer {
public void test(final int i){
new Dog(){
public void eat(){
for (int j = 0; j < i; j++){
System.out.println("匿名内部类~");
}
}
}.eat();
}
}
// 抽象类
abstract class Dog{
}
// 或者实现一个接口
interface Dog{
}
创建方式:
new 类/接口{
//匿名内部类实现部分
}
总结:
匿名内部类,也就是没有名字的内部类,正是因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
;
- 匿名内部类,必须继承一个抽象类或者实现一个接口;
- 匿名内部类,不能定义任何静态成员和静态方法;
- 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final;
- 匿名内部类不能是抽象的,它必须要实现继承的类或者是实现的接口所有抽象方法;