方法引用
方法引用: Lambda 的简化
1.方法引用是对Lambda的优化, 换句话说是在Lambda内部调用了方法
2.Lambda内部调用的方法使用的参数, 就是Lambda传递进来的参数
3.方法引用也遵循了之前学习的面向对象的理论知识
普通方法需要对象来调用
静态方法需要类来调用
public static void print(String s, Printable p) {
p.print(s);
}
public static void main(String[] args) {
print("Hello Lambda",
s -> {System.out.println(s);});
/**
* s -> System.out.println(s)
* 1.参数s 直接传给了 println 方法使用
* 2.System.out 对象本身就是存在的
* 3.println() 这个方法本身也是存在的
* 4.println方法的参数就是 接口方法的参数
* -- 就可以简化
*/
// 使用 方法引用 来简化Lambda
print("Hello Lambda", System.out::println);
}
通过对象名引用成员方法
步骤
1.准备一个函数式接口
2.准备一个方法 method, 用于接收 函数式接口 作为方法参数
3.准备一个类, 类中要有一个成员方法printUpperCase
4.因为要使用Lambda表达式, 所以需要调用 method 方法
并且需要在Lambda表达式内部调用 printUpperCase
printUpperCase方法的参数就是Lambda传递进来的参数
@FunctionalInterface
public interface Printable {
void print(String s);
}
public class MyObjectMethod {
public void printUpperCase(String s) {
System.out.println(s.toUpperCase());
}
public class Demo {
public static void method1(String s, Printable p) {
p.print(s);
}
public static void main(String[] args) {
/* method1("hello", s -> {
// 1.先创建MyObjectMethod对象
MyObjectMethod obj = new MyObjectMethod();
// 2.调用 printUpperCase 这个方法
obj.printUpperCase(s);
});*/
// 使用方法引用来优化
/*
1.对象已经存在 obj
2.方法已经存在 printUpperCase
*/
MyObjectMethod obj = new MyObjectMethod();
method1("hello", obj::printUpperCase);
}
通过类名引用静态方法
步骤
1.准备一个函数式接口
2.准备一个方法 cal, 用于接收 函数式接口 作为方法参数
3.准备一个类 Math , 类中要有一个静态方法 abs
4.因为要使用Lambda表达式, 所以需要调用 cal 方法
并且需要在Lambda表达式内部调用 Math.abs 静态方法
abs 方法的参数就是Lambda传递进来的参数
@FunctionalInterface
public interface Calcable {
int calAbs(int n);
}
public class Demo {
public static int cal(int n, Calcable c) {
return c.calAbs(n);
}
public static void main(String[] args) {
/*int t = cal(-10, n->{return Math.abs(n);});
System.out.println(t);*/
/**
* 1.方法 已经存在 abs
* 2.类存在 Math
*/
// 使用方法引用来优化
int t = cal(-10, Math::abs);
System.out.println(t);
}
通过super引用成员方法
步骤:
1.准备一个函数式接口
2.准备一个父类, 父类中有一个普通成员方法 hi(String)
3.准备一个子类[, 可以重写hi方法]
4.子类中要有一个sayHello方法, 用于接收 函数式接口 作为方法参数
5.在子类中再次准备一个方法, show(), 用于调用sayHello
可以传递Lambda表达式
需要在Lambda表达式中 调用 父类的hi方法
就会用到 super.hi(参数)
6.效果展示, 在主方法中调用show()
public interface Greetable {
void greet(String message);
}
public class Human {
public void hi(String message) {
System.out.println("hi Human!" + message);
}
}
public class Man extends Human {
// 重写的父类的hi方法
public void hi(String message) {
System.out.println("Hi Man!" + message);
}
// 定义一个sayHello, 目的是为了传入Lambda表达式
public void sayHello(String s, Greetable g) {
g.greet(s);
}
// 这个方法的目的, 是为了调用 sayHello
public void show() {
/* sayHello("吃了吗", s->{
// 调用父类的hi方法
super.hi(s);
});*/
/**
* 1.super对象已存在
* 2.方法hi已存在
*/
sayHello("吃了吗", super::hi);
}
public static void main(String[] args) {
new Man().show();
}
}
通过this引用成员方法
步骤:
1.准备一个函数式接口
2.准备一个类, 准备一个普通成员方法 buyHouse
3.类中要有一个 marry 方法, 用于接收 函数式接口 作为方法参数
4.在类中再次准备一个方法, show(), 用于调用 marry
可以传递Lambda表达式
需要在Lambda表达式中 调用 自己的 buyHouse 方法
就会用到 this.buyHouse(参数)
5.效果展示, 在主方法中调用show()
public interface Richable {
void buy(String str);
}
public class Husband {
public void buyHouse(String str) {
System.out.println("在" + str + "买了一套三居室");
}
public void marry(String str, Richable ric) {
ric.buy(str);
}
public void show() {
/*marry("北京三环内", s->{
this.buyHouse(s);
});*/
/**
* this 已经存在
* buyHouse 已经存在
*/
// 方法引用优化
marry("北京三环内", this::buyHouse);
}
public static void main(String[] args) {
new Husband().show();
}
类的构造器引用
Lambda表达式中使用了类的构造器
public interface PersonBuilder {
// 通过传入的name参数 构造一个Person对象并返回
// Person builderPerson(String name);
Person builderPerson();
public class Person {
private String name;
public Person() {
System.out.println("无参构造方法");
}
public Person(String name) {
this.name = name;
System.out.println("有参构造方法");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Demo {
public static void build(String name, PersonBuilder builder) {
/*Person person = builder.builderPerson(name);
System.out.println(person.getName());*/
Person person = builder.builderPerson();
System.out.println(person.getName());
}
public static void main(String[] args) {
// build("赵丽颖",
// name -> new Person(name));
// 构造器本身是存在的
build("赵丽颖", Person::new);
/*build("赵丽颖",
() -> new Person());*/
}
数组的构造器引用
Lambda表达式中创建了一个数组
public interface ArrayBuilder {
// 根据n - 数组长度, 来创建一个新的数组
int[] builderArray(int n);
}
public class Demo {
public static int[] builder(int n, ArrayBuilder arrBuild) {
return arrBuild.builderArray(n);
}
public static void main(String[] args) {
// int[] array = builder(10, n -> new int[n]);
int[] array = builder(10, int[]::new);
System.out.println(array.length);
}
}
RandomAccessFile
可读可写, 基于文件指针的操作
文件指针停留在哪里, 就可以操作文件的哪个位置
也可以手动指定文件指针的位置
指针位置的操作:
void skipBytes(跳过字节个数)
long getFilePointer() - 得到当前指针位置
void seek(long) - 指针定位到指定的位置
读写:
readInt/readDouble…
writeInt/writeDouble…
@Test
public void test01Write() throws IOException {
// 文件如果不存在, 会创建新的文件
// 文件如果存在, 原内容上直接写入新内容进行覆盖, 没有清空
RandomAccessFile rw = new RandomAccessFile("a.txt", "rw");
rw.write("你".getBytes());
rw.close();
}
@Test
public void test02Write() throws IOException {
RandomAccessFile rw = new RandomAccessFile("a.txt", "rw");
// 查看rw对象初始的文件指针位置
long filePointer = rw.getFilePointer();
System.out.println("初始指针位置: " + filePointer);
// 跳过前面6个字节, 再开始写入
rw.skipBytes(6);
System.out.println("跳过6个字节后位置: " + rw.getFilePointer());
rw.write("吃了吗".getBytes());
System.out.println("写完内容后的位置: " + rw.getFilePointer());
rw.close();
}
@Test
public void test03Write() throws IOException {
RandomAccessFile rw = new RandomAccessFile("a.txt", "rw");
rw.writeDouble(Long.MAX_VALUE);
System.out.println(rw.getFilePointer());
rw.close();
}
@Test
public void test01Read() throws IOException {
RandomAccessFile rw = new RandomAccessFile("a.txt", "rw");
double d = rw.readDouble();
System.out.println(d);
rw.close();
}
@Test
public void test02WriteAndRead() throws IOException {
RandomAccessFile rw = new RandomAccessFile("a.txt", "rw");
rw.writeLong(10l);
// 设置文件指针位置
rw.seek(0l);
double d = rw.readLong();
System.out.println(d);
rw.close();
}