内部类与Lambda表达式
学习内容
内部类
什么是内部类
一般来说,类与类之间的独立的,使用内部类能打破这种独立,让一个类成为内一个类的成员,与成员变量和成员方法同级。
为什么要使用内部类
采用内部类这种技术,可以隐藏内部的结构和细节,封装性更好。
内部类经过编译也会生成字节码文件,具体格式是这样的"OuterClass$InnerClass.class"
实例内部类
- 实例内部类必须用外部类实例来创建,和成员变量的使用方法是一致的
- 定义位置:类体中
在外部类的外部创建内部类对象
在外部类的内部创建内部类对象
静态内部类
- 静态内部类可以不通过外部类实例来创建,可以直接创建静态内部类实例
- 定义位置:类体中
局部内部类
- 定义位置:定义在方法的方法体中,注意:由于方法体中的代码是有执行顺序的,所以对局部内部类的声明最好写到方法体的开头位置
- 作用域:方法体中,从声明位置开始,到“}”结束
匿名内部类
1.没有名字的接口实现类
匿名内部类的使用
import java.util.Arrays;
import java.util.Date;
public class Test2 {
//使用匿名内部类给实例变量赋值
public A a = new A(){
public void method() {
System.out.println("method");
}
};
public static void main(String[] args) throws Exception{
//使用匿名内部类调用内部方法
new Test() {
public void test() {
System.out.println("test");
}
}.test();
//使用匿名内部类作为方法参数传入
method(new Test(){
public void test() {
System.out.println("test");
}
});
}
public static void method(Test test) {
test.test();
}
}
interface A {
void method();
}
interface Test {
void test();
}
四种内部类使用案例
public class Test1 {
public static void main(String[] args){
//调用实例内部类
new OuterClass().new InnerClass();
//调用静态内部类
OuterClass.StaticInnerClass.display();
//匿名内部类
new OuterClass().interface1.interMethod();
}
}
class OuterClass {
//Constructor
public OuterClass() {
System.out.println("OuterClass Constructor");
}
//1.实例内部类
class InnerClass {
public InnerClass() {
System.out.println("OuterClass InnerClass Constructor");
}
}
//内部类实例方法
public void outerClassMethod (){
System.out.println("OuterClass OuterClassMethod");
//2.局部内部类
class LocalInnerClass {
void display() {
System.out.println("OuterClass OuterClassMethod LocalInnerClass");
}
}
//调用局部内部类的方法
new LocalInnerClass().display();
}
//3.静态内部类
public static class StaticInnerClass {
static void display() {
System.out.println("OuterClass StaticInnerClass");
}
}
//4.匿名内部类
public Interface1 interface1 = new Interface1() {
public void interMethod() {
System.out.println("OuterClass Interface1 interMethod");
}
};
}
interface Interface1 {
void interMethod();
}
四种内部类编译后生成的字节码文件
Lambda表达式(箭头函数)与函数式接口
函数式接口
如果一个接口只有一个抽象方法,我们还可以将这个接口称作函数式接口,可以用注解@FunctionalInterface标识
Lambda表达式(箭头函数)Java8新特性
- 箭头函数要求必须用函数式接口接收(只有函数式接口才能使用箭头函数)
- 语法格式:(param1,param2) -> {方法体};
- 省略规则:
- 只有一个参数时,可以省略“()”
- 无返回值且方法体中只有一条java语句时,可以省略“{}”
Lambda使用代码
public class Test4 {
//有参数有返回值
Sum sum = (a,b) -> {return a+b;};
//有参数无返回值
Print print = (a) -> {
System.out.println("result2: " + a);
};
//无参数有返回值
Test1 test1 = () -> {return 3;};
//无参数无返回值
Test2 test2 = () -> {System.out.println("result4");};
、
public static void main(String[] args){
Test4 test = new Test4();
//1
int result1 = test.sum.sum(1,2);
System.out.println("result1: " + result1);
//2
test.print.print(1);
//3
int result3 = test.test1.test();
System.out.println("result3: " + result3);
//4
test.test2.test();
}
}
//有参有返回值
@FunctionalInterface
interface Sum {
int sum(int a,int b);
}
//有参无返回值
@FunctionalInterface
interface Print {
void print(int a);
}
//无参有返回值
@FunctionalInterface
interface Test1 {
int test();
}
//无参无返回值
@FunctionalInterface
interface Test2 {
void test();
}
匿名内部类与Lambda表达式的区别
所需类型不同
1.匿名内部类:可以是接口,抽象类,具体类
2.Lambda表达式:只能是接口
使用限制不同
1.如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
2. 如果接口中多于一个抽象方法,就只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同:
1.匿名内部类:编译之后,产生一个单独的.class字节码文件
2.Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成