面向对象
文章目录
匿名类
当接口、抽象类的实现类,在整个项目中只用过一次,可以考虑使用匿名类
案例
public interface Eatable {
String name();
int energy();
}
public class Person {
public void eat(Eatable a) {
System.out.println("eat - " + a.name() + " -" + a.energy());
}
}
public static void main(String[] args) {
Person person = new Person();
person.eat(new Eatable() { // 匿名内部类
@Override
public String name() {
return "Apple";
}
@Override
public int energy() {
return 100;
}
}); // eat - Apple -100
Eatable beef = new Eatable() {
@Override
public String name() {
return "Beef";
}
@Override
public int energy() {
return 200;
}
};
person.eat(beef); // eat - beef -200
}
文章目录
基本使用
匿名类不能定义除 编译时常量(static int final a = 1
) 以外的任何 static 成员
匿名类只能访问 final
或者 有效final
的局部变量
“有效 final 的局部变量” 就是指只被赋值过一次的局部变量
匿名类可以直接访问外部类中的所有成员(即使被声明为 private)
匿名类只有在实例相关的代码块中使用,才能直接访问外部类中的实例成员(实例变量、实例方法)
匿名类不能自定义构造方法,但可以有初始化块
用途
匿名类的常见用途
- 代码传递
- 过滤器
- 回调
匿名类 - 代码传递 - 测试代码运行时间的工具类
public class Times {
public interface Block {
void execute();
}
public static void test(Block block) {
long begin = System.currentTimeMillis();
block.execute();
long end = System.currentTimeMillis();
long duration = end - begin;
System.out.println("花费时间" + duration + "ms");
}
}
小提示:字符串拼接相当耗时
public static void main(String[] args) {
Times.test(new Block() {
@Override
public void execute() {
String str = "";
for (int i = 0; i < 10000; i++) {
// 字符串拼接极其耗时间, 因为每次都相当于创建新的对象
str += i;
}
}
});
}
匿名类 - 回调 - 简易网络请求
public class Networks {
public interface Block {
void success(Object response);
void failure();
}
public static void get(String url, Block callBack) {
// 1. 根据url发送一个异步请求(开启一条子线程)
// ......
// 2. 请求完毕后
boolean result = url.contains("666") ? true : false;
if (result) {
Object response = null;
callBack.success(response);
} else {
callBack.failure();
}
}
public static void main(String[] args) {
// 传入的网络请求只有满足某些条件时会返回成功, 其他情况会失败
// 但是发送请求时将成功要做的事的和失败要做的事都写好了
// 等到判断条件是否满足以后再回来调用, 这就是回调
Networks.get("http://xxx.com?pwd=666", new Block() {
@Override
public void success(Object response) {
System.out.println("请求成功");
}
@Override
public void failure() {
System.out.println("请求失败");
}
});
}
}
匿名类 - 过滤器 - 获取目录下的所有文件
public class Files {
public interface Filter {
boolean accpet(String filename);
}
// 需要传入一个Filter过滤器, 用来自定义要返回满足哪些条件的文件名
public static String[] getAllFileNames(String dir, Filter filter) {
// 1.先获取 dir 文件夹下的所有文件名
String[] allFilesnames = {};
// 2.进行过滤
for (String filename : allFilesnames) {
if (filter.accpet(filename)) {
// 将满足条件的文件名装起来
}
}
// 返回所有装起来的文件名(满足条件的文件名)
return null;
}
public static void main(String[] args) {
// 获取F盘下所有.java文件
Files.getAllFileNames("F:", new Filter() {
@Override
public boolean accpet(String filename) {
if (filename.endsWith(".java")) return true;
return false;
}
});
// 获取F盘下所有名字中带hello的文件
Files.getAllFileNames("F:", new Filter() {
@Override
public boolean accpet(String filename) {
if (filename.contains("hello")) return true;
return false;
}
});
}
}
排序
Arrays.sort()
可以使用 JDK 自带的 java.util.Arrays
类中的sort()
方法对数组进行排序;
Arrays.sort
默认是升序排列,可以通过比较器Comparator
改变次序- 把比较小的元素放左边
- 把比较大的元素放右边
compare
的返回值- 等于 0 :
o1 == o2
- 大于 0 :
o1 > o2
- 小于 0:
o1 < o2
- 等于 0 :
Integer[] array = { 33, 22, 11, 77, 66, 99 };
Arrays.sort(array);
System.out.println(Arrays.toString(array));
// [33, 22, 11, 77, 66, 99]
Arrays.sort(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
System.out.println(Arrays.toString(array));
// [11, 22, 33, 66, 77, 99]
Lambda
基本使用
Lambda 表达式是 Java 8 开始才有的语法
- 函数式接口(Functional Interface):只包含 1 个抽象方法的接口
可以在接口上面加上@FunctionalInterface
注解,表示它是一个函数式接口 - 当匿名类实现的是函数式接口时,可以使用 Lambda 表达式进行简化
@FunctionalInterface
public interface Testable {
void test(int v);
}
注意事项
- 参数列表可以省略参数类型
- 当只有一条语句时,可以省略大括号、分号、
return
- 当只有一个参数时:可以省略小括号
- 当没有参数时:不能省略小括号
Lambda 表达式示例
public interface Caculator {
int caculate(int v1, int v2);
}
static void execute(int v1, int v2, Caculator c) {
System.out.println(c.caculate(v1, v2));
}
public static void main(String[] args) {
execute(10, 20, (int v1, int v2) -> {
return v1 + v2; // 20
});
execute(11, 22, (v1, v2) -> v1 + v2); // 20
}
使用注意
使用注意
- Lambda 只能访问
final
或者 有效 final 的局部变量 - Lambda 没有引入新的作用域
public class OuterClass {
@FunctionalInterface
public interface Testable {
void test(int v);
}
private int age = 1;
public class InnerClass {
private int age = 2;
void inner() {
// int v = 4; // error, Lambda 没有引入新的作用域, 重复定义变量
Testable t1 = v -> {
System.out.println(v); // 3
System.out.println(age); // 2
System.out.println(this.age); // 2
System.out.println(InnerClass.this.age); // 2
System.out.println(OuterClass.this.age); // 1
};
t1.test(3);
Testable t2 = new Testable() {
@Override
public void test(int v) {
System.out.println(v); // 3
System.out.println(age); // 2
// System.out.println(this.age); // error
System.out.println(InnerClass.this.age); // 2
System.out.println(OuterClass.this.age); // 1
}
};
t2.test(3);
}
}
public static void main(String[] args) {
new OuterClass().new InnerClass().inner();
}
}
方法引用
如果 Lambda 中的内容仅仅是调用某个方法,可以使用方法引用(Method Reference)来简化
引用静态方法
@FunctionalInterface
public interface Testable {
int test(int v1, int v2);
}
public static void main(String[] args) {
Testable t1 = (v1, v2) -> Math.max(v1, v2);
System.out.println(t1.test(10, 20)); // 20
Testable t2 = Math::max; // 引用静态方法
System.out.println(t2.test(10, 20)); // 20
}
引用特定对象的实例方法
@FunctionalInterface
public interface Testable {
void test(int v);
}
public class Person {
public void setAge(int age) {
System.out.println("Person - setAge - " + age);
}
static void execute(Testable t, int v) {
t.test(v);
}
public static void main(String[] args) {
// 10
execute(v -> System.out.println(v), 10);
// 20
execute(System.out::println, 20); // 引用特定对象的实例方法
// Person - setAge - 10
execute(v -> new Person().setAge(v), 10);
// Person - setAge - 20
execute(new Person()::setAge, 20); // 引用特定对象的实例方法
}
}
引用特定类型的任意对象的实例方法
String[] strings = { "Jack", "james", "Apple", "abort" };
// [abort, Apple, Jack, james]
Arrays.sort(strings, (s1, s2) -> s1.compareToIgnoreCase(s2));
// [abort, Apple, Jack, james]
Arrays.sort(strings, String::compareToIgnoreCase); // 引用特定类型的任意对象的实例方法
引用构造方法
public class Person {
@FunctionalInterface
public interface Testable {
Object test(int v);
}
public Person(int age) { // 构造方法
System.out.println("Person - " + age);
}
public static void main(String[] args) {
Testable t1 = v -> new Person(v);
// Person - 18
// com.mj.Person@816f27d
System.out.println(t1.test(18));
// Person - 18
// com.mj.Person@6ce253f1
Testable t2 = Person::new; // 引用构造方法
System.out.println(t2.test(18));
}
}
引用数组的构造方法
@FunctionalInterface
public interface Testable {
Object test(int v);
}
public static void main(String[] args) {
Testable t1 = v -> new int[v];
System.out.println(((int[])t1.test(3)).length);
Testable t2 = int[]::new; // 引用数组的构造方法
System.out.println(((int[])t2.test(3)).length);
引用当前类中定义的实例方法
public class Person {
public void setAge(int age) {
System.out.println("Person - setAge - " + age);
}
public void show() {
Testable t1 = v1 -> setAge(v);
// Person - setAge - 10
t1.test(10);
Testable t2 = this::setAge; // 引用当前类中定义的实例方法
// Person - setAge - 10
t2.test(10);
}
}
引用父类中定义的实例方法
@FunctionalInterface
public interface Testable {
void test(int v);
}
class Person {
public void setAge(int age) {
System.out.println("Person - setAge - " + age);
}
}
public class Studen extends Person {
public void setAge(int age) {
System.out.println("Student - setAge - " + age);
}
public void show() {
Testable t1 = v -> super.setAge(v);
// Student - setAge - 10
t1.test(10);
Testable t2 = super::setAge; // 引用父类中定义的实例方法
// Student - setAge - 10
t2.test(10);
}
}