在Java类下,使用 { } 括起来的代码被称为代码块
局部代码块
位置:方法中定义
作用:限定变量的生命周期,及早释放,提高内存利用率
构造代码块
位置:类中方法外定义
特点:每次构造方法执行的时,都会执行该代码块中的代码,并且在构造方法执行前执行
作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
随便创造一个类后再含有主方法的类中调用执行,源代码与结果如下
class Testdemo{
{
System.out.println("这是测试类的构造代码块");
}
public Testdemo(){
System.out.println("空参");
}
public Testdemo(int num){
System.out.println("带参");
}
}
静态代码块
位置:类中方法外定义
特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
作用:在类加载的时候做一些数据初始化的操作
内部类
内部类就是定义在一个类里面的类 创建格式: 格式:外部类名.内部类名 对象名 = new 外部类对象().new 内部类对象(); 范例:Outer.Inner in = new Outer().new Inner(); 内部类成员访问 内部类中, 访问外部类成员 : 直接访问, 包括私有 外部类中, 访问内部类成员 : 需要创建对象访问 内部类的访问特点(内部类封装性更好) 内部类可以直接访问外部类的成员,包括私有 外部类要访问内部类的成员,必须创建对象
内部类的简单使用
public class interal_lei_ues {
public static void main(String[] args) {
Outer0.Inter demo1 = new Outer0().new Inter();
System.out.println(demo1.number);
demo1.show();
}
}
class Outer0 {
int number = 10;
public void way1(){
System.out.println("这是外部类 : "+number);
}
class Inter {
int number = 100;
public void show() {
System.out.println(Outer0.this.number + " " + number);
System.out.println("这是内部类");
way1();
}
}
}
cl
多个成员变量时内部类对各层次变量的调用
class Outer1 {
int num = 150;
class Inner {
int num = 110;
public void show(){
int num = 78;
System.out.println(num); // 78
System.out.println(this.num); // 110
System.out.println(Outer1.this.num); // 150
}
}
}
内部类分类:
静态内部类
静态内部类:有 static 修饰的成员内部类 格式:外部类名.内部类名 对象名 = new 外部类名.内部类对象(); 范例:Outer.Inner in = new Outer.Inner(); 注意事项 : 静态只能访问静态(静态的内部类想要使用外部非静态的变量时,就得创建一个1对象)
class Outer {
static class Inner { }
}
局部内部类
局部内部类:局部内部类放在方法、代码块、构造器等执行体中。
注意: 当方法的传入类型是接口类型时,我们传入的是该接口的实现类型
匿名内部类
概述:匿名内部类本质上是一个特殊的局部内部类(定义在方法内部) 前提:需要存在一个接口或类 格式: new 类名 / 接口 () { } new 接口 代表实现这个接口 new 类名 代表继承这个类 匿名内部类可以使代码更加简洁,定义一个类的同时对其进行实例化
在不使用内部匿名类的情况下在主方法下创建一个直接使用接口的方法如下及成果
public static void main(String[] args) {
System.out.println("**********************匿名类**********************");
useInter(new Inter_one());
}
public static void useInter(Inter i){
i.show();
}
}
interface Inter{
void show();
}
class Inter_one implements Inter{
public void show(){
System.out.println("这是测试接口下的第一个实现类");
}
}
使用内部类的过程及效果
public class interal_lei_ues {
System.out.println("**********************匿名类**********************");
useInter(new Inter_one());
//使用匿名内部类的方法
useInter(new Inter() {
@Override
public void show() {
System.out.println("这是匿名内部类使用接口类型的第一次尝试");
}
});
}
public static void useInter(Inter i){
i.show();
}
}
介绍 : 先创建一个函数式的接口,由于接口的特性,我们无法直接创建该对象(与多态无关,多态创建后里面也是null一堆抽象方法也调用不了),所以我们在含有主方法的类中创建一个静态的方法(使得不用创建该方法时,main方法也能调用),要使用该方法,原本我们可以在接口的基础上创建一个子类,后在main方法中创建该类的对象,再导入该方法中,也可以直接new一个该类使用该方法,现在我们可以使用匿名内部类(类似上述的在接口下的子类)
Lamda表达式
Lambda表达式是 JDK8 开始后的一种新语法形式。 作用:简化匿名内部类的代码写法。 Lambda表达式的简化格式 : () -> {} (匿名内部类被重写方法的形参列表) -> { 被重写方法的方法体代码。 } 注:-> 是语法形式,无实际含义 注意:Lambda 表达式只能简化函数式接口的匿名内部类的写法形式
函数接口: 首先必须是接口、其次接口中有且仅有一个抽象方法的形式 通常我们会在接口上加上一个@FunctionalInterface注解,标记该接口必须是满足函数式接口
@FunctionalInterface
interface Inter{
void show();
}
简单用lambda表达式创建一个匿名内部类(引用上文useInter方法和相应的接口)
//使用lambda表达式创建匿名内部类的方法
useInter(() -> {
System.out.println("这是用lambda匿名内部类使用接口类型的第二次尝试");
}); //此时lambda表达式对应的的是接口中的show方法所以()不用添加东西
书接上文 : 如果该接口属于函数接口时,我们就可以使用lambda表达式,对上面的内部类再一次进行简化
Lambda表达式的省略写法细节 参数类型可以省略不写。 如果只有一个参数,参数类型可以省略,同时 () 也可以省略。
public class interal_lei_ues {
public static void main(String[] args) {
useInter1(new Inter1() {
@Override
public void printfMassage(String msg) {
System.out.println("这是匿名内部类使用接口类型,重写后的代码"+msg);
}
});
useInter1((msg)->{ //此时括号内参数没有参数类型,没有报错
System.out.println("这是使用lambda匿名内部类使用接口类型,重写后的代码"+msg);
});
useInter1(msg->{ //此时只有一个参数不加()系统没有报错
System.out.println("这是使用lambda匿名内部类使用接口类型,重写后的代码"+msg);
});
}
public static void useInter1(Inter1 i){
i.printfMassage("nihaodayi");
}
}
@FunctionalInterface
interface Inter1{
void printfMassage(String msg);
} //创建一个含参数的函数式接口
如果Lambda表达式的方法体代码只有一行代码可以省略大括号不写,同时要省略分号
useInter(() -> System.out.println("这是用lambda匿名内部类使用接口类型的第二次尝试"));
此时,如果这行代码是return语句,必须省略return不写,同时也必须省略 ";" 不写
Lambda表达式和匿名内部类的区别
使用限制不同 匿名内部类 : 可以操作类, 接口 Lambda表达式 : 只能操作函数式接口 实现原理不同 匿名内部类:编译之后,产生一个单独的.class字节码文件 Lambda表达式:编译之后,没有一个单独的.class字节码文件