Java内部类

学习java的过程中发现内部类是java的一个非常重要的组成部分,因此把自己的学习成果总结出来。

概念

内部类是指在外部类中被定义的类

分类

内部类根据是否有类名以及是否被static修饰,可以分成有名内部类、匿名内部类和静态内部类和非静态内部类四种。(注:静态内部类同时也是有名内部类和匿名内部类的其中一种。)

有名内部类

有名称的内部类就是内部类,这其中根据内部类的定义位置,又可以分为成员内部类和局部内部类两种。

成员内部类

成员内部类是内部类最普通的类型,它的定义是位于另一个类的内部,例如:

class body{				//外部类
	int height;
	class heart{			//成员内部类
		System.out.println("The heart is beating!");
	}
}

从上面的代码中可以这样看,heart类就好像body类的一个成员一样,heart就称为成员内部类,外面的类,即body类就被称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括有private或static修饰词修饰的成员)。
但是,如果内部类中存在与外部类中名称相同的成员属性或者方法,默认情况下调用的是内部类中的同名成员,如果需要调用外部类中的同名成员,则需要这样进行调用:

外部类.this.同名成员

外部类若想访问内部类的成员,需要创建一个内部类的实例对象,再通过指向这个对象才能进行访问。
内部类同样可以使用public,protected,private及默认访问权限,具体的用法与一般的成员一样。

局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

class People{
    public People() {
         
    }
}
 
class Man{				//外部类
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部内部类
            int age =0;
        }
        return new Woman();
    }
}

局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

匿名内部类

匿名内部类是java中运用最多的内部类。
由于匿名内部类没有类名存在,定义匿名内部类的同时就必须将其实例化,具体代码格式如下:

new 父类构造器(参数列表)|接口(){
	//匿名内部类类体
}

匿名内部类的特点包括:
1.匿名内部类的实质:
    在普通类中,匿名内部类的实质为普通类的子类。
    在抽象类中,匿名内部类的实质为抽象类的子类。
    在接口中,匿名内部类的实质为接口的实现类。
    匿名内部类一定是以上三中的其中一种。
2.匿名内部类不能自定义构造方法,但是可以通过非静态代码块初始化成员变量。
3.匿名内部类一定不能是抽象类。
4.匿名内部类中新添加的属性和方法不能被上转型对象所调用,只能被非上转型方式创建的匿名内部类对象所调用。

静态内部类

内部类按照是否有static修饰分为静态内部类和非静态内部类,有static修饰的为静态内部类,没有static修饰的为非静态内部类,前面讲的全都是非静态内部类。
若要跨类使用静态有名内部类,则必须以以下形式创建其对象:

内部类名 clazz = new 外部类名.内部类名

静态内部类的特点包括:
1.静态内部类仅能直接访问外部类的静态成员变量和方法,可以通过创建外部类的对象间接使用非静态的成员变量和方法。
2.在非外部类中定义的内部类和局部变量一样,其使用范围从定义的位置开始到其所在直接语句块结束。
3.只有有名静态内部类中才允许有静态成员。

内部类的特点

综合所有内部类,他们共同的特点有:
1.内部类是一个独立的类:编译之后内部类会被编译成独立的.class文件,如果该内部类为有名内部类,则有名内部类字节码文件名为外部类的类名+$+内部类类名;如果为匿名内部类,则匿名内部类字节码文件名为外部类类名+$+数字。
2.普通外部类、抽象类和接口都可以有内部类(匿名的和有名的皆可)
3.内部类可以直接定义在类中,也可以定义在方法或代码块中;其中直接定义在外部类中的内部类可以被public等四种访问权限修饰(注:普通外部类、接口和抽象类只能使用public和default修饰),也可以使用static修饰(注:static不能修饰普通外部类、接口和抽象类);但是定义在方法或代码块中的内部类不能有访问修饰符修饰,也不能有static修饰。
4.内部类可以访问外部类的所有访问权限的成员变量。
5.在局部变量作用的范围内,如果定义的内部类需要使用该局部变量,则改变量必须有final修饰。

Lambda表达式

在Java8版本后,Java支持了Lambda表达式,大的出现简化了函数式接口匿名内部类的语法,表达式语法如下:

(参数)->{代码块}

简单且不准确的来说,Lambda表达式其实就是把一串代码赋给了一个变量。例如:

匿名内部类:
import java.util.Date
public class Test {
	public static void main(String[] args) {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println(new Date());
			}
		};
		new Thread(runnable).start();
	}
}

这是一个匿名内部类,显然,为了这个内部类我们写了很多的代码。而Lambda表达式可以把这些臃肿的代码减少:

Lambda 表达式:
import java.util.Date;
public class Test {
	public static void main(String[] args) {
		new Thread(() -> {
			System.out.println(new Date());
		}).start();
	}
}

将匿名内部类改写成Lambda表达式可以大大增加代码的可读性和减少代码的臃肿。
Lambda表达式其实还有非常多的知识,详细的内容可以在@槿。。。Lambda 表达式有何用处?中进行进一步的学习。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值