Java代码块、内部类与Lambda指南
·
代码块
认识代码块
- 代码块是类中的5大成分之一(成员变量、构造器、方法、代码块、内部类)。
代码块分为:
- 静态代码块:
- 格式:static{}
- 特点:类加载时自动执行(与类一起优先加载),由于类只会加载一次,所以静态代码也只会执行一次。
- 作用:完成类的初始化,例如:对静态变量的初始化赋值。
- 实例代码块:
- 格式:{}
- 特点:每次创建对象时,执行实例代码块,并在构造器前执行。
- 作用:和构造器一样都是用来完成对象的初始化的(初始化对象的实例资源),例如:对实例变量进行初始化赋值。
内部类
认识内部类
-
如果一个类定义在另一个类的内部,这个类就是内部类。
-
场景:当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类
public class Car{ //内部类 public class Engine{ } }
成员内部类
-
就是类中的一个普通成员,类似前面我们学过的普通成员变量、成员方法。
public class Outer{ //成员内部类 public class Inner{ } } -
成员内部类创建对象的格式:
外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称;
Outer.Inner oi=new Outer().new Inner(); -
成员内部类访问外部成员的特点(拓展):
- 1、成员内部类中可以直接访问外部类的实例成员、静态成员
- 2、成员内部类的实例方法中,可以直接拿到当前寄生的外部类对象:外部类名.this / 外部类名.this.方法
静态内部类
-
有static修饰的内部类,属于外部类自己持有。
public class Outer{ //静态内部类 public static class Inner{ } }外部类名.内部类名 对象类=new 外部类.内部类(); Outer.Inner in=new Outer.Inner(); -
特点:
- 可以直接访问外部类的静态成员,不可以直接访问外部类的实例成员。
局部内部类(了解)(鸡肋语法)
- 局部内部类是定义在方法中、代码块中、构造器等执行体中。
匿名内部类(重点)
认识匿名内部类
- 一种特殊的局部内部类;
- 所谓匿名:指的是程序员不需要为这个类声明名字,默认有个隐藏的名字。
new 类或接口(参数值...){
类体(一般是方法重写);
};
- 特点:匿名内部类本质就是一个子类,并会立即创建出一个子类对象。
- 作用:用于方便的创建一个子类对象。
常见使用形式
- 通常作为一个对象参数传输给方法。
- 需求:例如:学生老师参加游泳比赛
//Swimming接口
public interface Swimming {
void swim();
}
//Test类
public class Test {
public static void main(String[] args) {
Swimming s1 = new Swimming() {
@Override
public void swim() {
System.out.println("学生游泳飞快~~~");
}
};
go(s1);
go(new Swimming() {
@Override
public void swim() {
System.out.println("老师游泳还行~~~");
}
});
}
public static void go(Swimming s) {
System.out.println("开始===========");
s.swim();
}
}
匿名内部类的使用场景
- 调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象給其使用。
- 开发中不是我们要主动去写匿名内部类,而是用别人功能时,别人可以让我们写一个匿名内部类,我们才会写。
- 使用comparator接口的匿名内部类实现对数组进行排序
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("玛卡巴卡", 16, 170.1);
students[1] = new Student("唔西迪西", 12, 158.2);
students[2] = new Student("依古比古", 18, 168.5);
// 使用Comparator接口的匿名内部类,按年龄升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});
// 打印排序后的数组
System.out.println(Arrays.toString(students));
}
}
函数式编程
函数式编程解决了什么问题?
- 使用Lambda函数替代某些匿名内部类对象,从而让程序代码更简洁,可读性更好。
Lambda
认识Lambda
-
JDK 8开始新增的一种语法形式,它表示函数
-
可以用于替代某些匿名内部类对象,从而让程序更简洁,可读性更好。
(被重写方法的形参列表)->{ 被重写方法的方法体代码。 } -
注意:Lambda表达式只能替代函数式接口的匿名内部类!!!
-
什么是函数式接口?
- 有且仅有一个抽象式方法的接口。
- 注意:将来我们见到的大部分函数式接口,上面都可能会有一个@FunctionalInterface 的注解,该注解用于约束当前接口必须是函数式接口。
实战实例
- 使用Lambda简化comparator接口的匿名内部类
public class Test {
public static void main(String[] args) {
Student[] students = new Student[3];
students[0] = new Student("玛卡巴卡", 16, 170.1);
students[1] = new Student("唔西迪西", 12, 158.2);
students[2] = new Student("依古比古", 18, 168.5);
// 使用Comparator接口的匿名内部类,按年龄升序排序
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});
//lambda简化后:
Arrays.sort(students, (Student o1, Student o2)->{
return o1.getAge() - o2.getAge();
}
});
// 打印排序后的数组
System.out.println(Arrays.toString(students));
}
}
Lambda表达式省略规则:
-
作用:用于进一步简化Lambda表达式的写法。
-
具体规则:
- 参数类型可以省略不写。
Arrays.sort(students, (o1, o2)->{ return o1.getAge() - o2.getAge(); } });- 如果只有一个参数,参数类型省略的同时"()“也可以省略,但多个参数不能省略”()"
- 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号";"如果这行代码是return语句,也必须去掉return。
Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge() );
方法引用
静态方法的引用
-
类名::静态方法
-
使用场景
- 如果某个Lambda表达式里只是调用一个静态方法,并且”->“前后参数的形式一致,就可以使用静态方法引用。
//静态方法: public static int compareByAge(Student o1,Student o2){ return o1.getAge()-o2.getAge(); } //简化前: Arrays.sort(students,(o1,o2) -> Student.compareByAge(o1,o2)); //静态方法引用: Arrays.sort(students,Student::compareByAge);
实例方法引用
-
对象名::实例方法
-
使用场景
- 如果某个Lambda表达式里只是调用一个实例方法,并且”->“前后参数的形式一致,就可以使用实例 方法引用。
//实例方法: public int compareByHeight(Student o1,Student o2){ return Double.compare(o1.getHeight(),o2.getHeight()); } //调用方法 Student s1=new Student(); //简化前 Arrays.sort(students,(o1,o2) -> s1.compareByHeight(o1,o2)); //简化后: Arrays.sort(students,s1::compareByHeight);
特定型的方法引用
-
特定类的名称::方法
-
使用场景
- 如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。
//Java提供的字符串按首字母忽略大小写比较的方法:compareToIgnoreCase Arrays.sort(names, (o1,o2) -> o1.compareToIgnoreCase(o2)); //简化后: Arrays.sort(names, String::compareToIgnoreCase);
构造器引用
-
类名::new
-
使用场景
- 如果某个Lambda表达式里只是创建对象,并且“->”前后参数情况一致,就可以使用构造器引用。
//创建接口的匿名内部类对象: CarFactory cf= new CarFactory() { @Override public Car getCar(String name){ return new Car(name); } }; //化简前: CarFactory cf =name -> new Car(name); //简化后: CarFactory cf =Car::new;
更多推荐
所有评论(0)