方法引用: Lambda 的简化
对象 类 this super 数组
普通方法 静态方法 构造方法 new数组
1.方法引用是对Lambda的优化, 换句话说是在Lambda内部调用了方法
2.Lambda内部调用的方法使用的参数, 就是Lambda传递进来的参数
3.方法引用也遵循了之前学习的面向对象的理论知识
普通方法需要对象来调用
静态方法需要类来调用
…
a.准备一个函数式接口
b.准备一个方法 method, 用于接收 函数式接口 作为方法参数
c.准备一个类, 类中要有一个成员方法printUpperCase
d.因为要使用Lambda表达式, 所以需要调用 method 方法
并且需要在Lambda表达式内部调用 printUpperCase
printUpperCase方法的参数就是Lambda传递进来的参数
a.准备一个函数式接口
b.准备一个方法 cal, 用于接收 函数式接口 作为方法参数
c.准备一个类 Math , 类中要有一个静态方法 abs
d.因为要使用Lambda表达式, 所以需要调用 cal 方法
并且需要在Lambda表达式内部调用 Math.abs 静态方法
abs 方法的参数就是Lambda传递进来的参数
1和2的代码实现
//准备一个函数式接口
@FunctionalInterface
public interface ObjectReference {
public abstract void method(String str);
}
//准备一个函数式接口
@FunctionalInterface
public interface ClassReference {
//定义唯一方法的返回值类型和参数
public abstract void abs(int i);
}
public class ObjectAndClassReferenceTest {
//准备一个方法,用于接收函数式接口作为方法参数
public static void printUppercase(ObjectReference tfi, String s){
//使用函数式接口的方法输出s的大写表示
tfi.method(s);
}
//准备一个方法,用于接收函数式接口作为方法参数
public static void printAbs(ClassReference tf, int i){
//使用函数式接口的方法输出i的绝对值
tf.abs(i);
}
public static void main(String[] args) {
ReferenceClass testClass = new ReferenceClass();
//使用对象引用普通成员方法
printUppercase(testClass::printUpperCase, "hello");
//使用类引用静态成员方法
printAbs(ReferenceClass::printAbs, -10);
}
}
a.准备一个函数式接口
b.准备一个父类, 父类中有一个普通成员方法 hi(String)
c.准备一个子类[, 可以重写hi方法]
d.子类中要有一个sayHello方法, 用于接收 函数式接口 作为方法参数
e.在子类中再次准备一个方法, show(), 用于调用sayHello
可以传递Lambda表达式
需要在Lambda表达式中 调用 父类的hi方法
就会用到 super.hi(参数)
f.效果展示, 在主方法中调用show()
a.准备一个函数式接口
c.准备一个类, 准备一个普通成员方法 buyHouse
d.类中要有一个 marry 方法, 用于接收 函数式接口 作为方法参数
e.在类中再次准备一个方法, show(), 用于调用 marry
可以传递Lambda表达式
需要在Lambda表达式中 调用 自己的 buyHouse 方法
就会用到 this.buyHouse(参数)
f.效果展示, 在主方法中调用show()
3和4的代码实现
public interface SuperReference {
public abstract void sayHello(String name);
}
//准备一个函数式接口
public interface ThisReference {
public abstract void buyHouse(int price);
}
//准备一个父类
public class Human {
private String name;
private int age;
public Human() {
}
public Human(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//父类中有一个普通成员方法
public void sayHello(String s){
System.out.println("hello! " + s);
}
//准备一个普通成员方法
public void buyHouse(int price){
System.out.println("我买了" + price + "的房子");
}
//准备一个方法用于接收函数式接口作为参数
private void buy(ThisReference tr, int price){
tr.buyHouse(price);
}
//准备一个方法拥有调用使用函数式接口为参数的方法
public void show(int price){
buy(new ThisReference() {
@Override
public void buyHouse(int price) {
Human.this.buyHouse(price);
}
}, price);
}
//使用方法引用简化
public void showReference(int price){
buy(this::buyHouse, price);
}
}
import org.junit.Test;
//准备一个子类
public class My extends Human{
public My() {
}
//在子类中要有一个方法用于接收函数式接口参数
private void sayHello(SuperReference si, String s){
si.sayHello(s);
}
//在子类中在准备一个方法,调用使用函数式接口作为参数的成员方法,并且使用父类的成员方法实现了这个函数式接口
public void show(){
sayHello(new SuperReference() {
@Override
public void sayHello(String name) {
//调用父类的方法重写函数式接口方法
My.super.sayHello(name);
}
}, "hzt");
}
//使用方法引用简化show
@Test
public void showReference(){
sayHello(super::sayHello, "hzt");
}
}
public class SuperAndThisReferenceTest {
public static void main(String[] args) {
//super引用效果展示
My my = new My();
my.showReference();
//this引用效果展示
Human human = new Human();
human.showReference(2000000);
}
}
Lambda表达式中使用了类的构造器
public interface ConstructInterface {
public abstract Human build(String name, int age);
}
public class ConstructReference {
public static Human build(ConstructInterface ci, String name, int age){
return ci.build(name, age);
}
public static void main(String[] args) {
//类的构造器的引用
Human hzt = build(Human::new, "hzt", 20);
System.out.println(hzt.getName() + hzt.getAge() + "岁");
}
}
Lambda表达式中创建了一个数组
public interface ArrayInterface {
public abstract int[] build(int length);
}
public class ArrayReference {
public static int[] build(ArrayInterface ai, int i){
return ai.build(i);
}
public static void main(String[] args) {
//数组构造器重写接口
int[] a = build(new ArrayInterface() {
@Override
public int[] build(int length) {
return new int[length];
}
}, 5);
//使用方法引用简化引用数组构造器
int[] b =build(int[]::new, 5);
System.out.println(b.length);
}
}
RandomAccessFile - 可读可写, 基于文件指针的操作
文件指针停留在哪里, 就可以操作文件的哪个位置
也可以手动指定文件指针的位置
指针位置的操作:
void skipBytes(跳过字节个数)
long getFilePointer() - 得到当前指针位置
void seek(long) - 指针定位到指定的位置
读写:
readInt/readDouble…
writeInt/writeDouble…
代码实现:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileAPI {
//该类的实例支持读取和写入随机访问文件。 随机访问文件的行为类似于存储在文件系统中的大量字节。
//有一种游标,或索引到隐含的数组,称为文件指针 ; 输入操作读取从文件指针开始的字节,并使文件指针超过读取的字节。
public static void main(String[] args) throws IOException {
File file = new File("./src/javaSE/random_access_file/raf.txt");
//创建文件随机访问类(注意其不是I/O流),模式为可读可写
System.out.println(file.getAbsolutePath());
RandomAccessFile raf = new RandomAccessFile(file, "rw");
//写入一个long的最大值
raf.writeLong(Long.MAX_VALUE);
//读取一个long值,因为每次读或者写行为完成后都会将文件指针后移一位,所以想要读取之前写入的数据就必须重设指针位置
//否则就会抛出EOF即文件结束异常
//获取当前指针位置
long place = raf.getFilePointer();
System.out.println(place);
//设置指针位置为0,即从头开始读
raf.seek(0);
//从当前文件指针读取一个long类型数据,即8字节
long l = raf.readLong();
System.out.println(l);
//尝试跳过 n字节的输入丢弃跳过的字节。
raf.seek(0);
raf.skipBytes(4);
System.out.println(raf.getFilePointer());
}
}