Javaday32 Java8新特性 Lambda表达式

����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

Java8

整型常量(JDK7.0之后)

在Java8中整型常量可以用下划线分隔表示,这样的目的是为了更方便阅读

int a = 100_000;
//下划线不能写在最开始的位置和最末尾的位置
//下划线不能写在小数点左右两边
int b = _10,c = 10_;
double d = 10._0,e = 10_.0;

I/O流的释放(jdk7.0之后)

为了简化代码并且不抛出异常,新增了IO流资源释放的方式,可以将流的定义创建写入到try()的括号中,就相当于作为这个方法的变量,这样可以减少异常的出现(例如空指针异常等)和简化代码,如果同时创建多个流需要用分号隔开,因为创建一个流就相当于一个语句。

	try(FileOutputStream out =new FileOutputStream("A.txt");
				FileInputStream in = new FileInputStream("A.txt")) {
			byte[] buf = new byte[1024];
			out.write("石原里美".getBytes());
			in.read(buf);
			System.out.println(Arrays.toString(buf));
			in.close();
			out.close();
		} catch (Exception e) {
		}

接口方法

在JDK1.8之后,接口中不仅只有抽象方法,还可以静态方法和默认方法,这是因为当我们已经实现了接口原本有的抽象方法之后,又新增了其他的方法,那么所有的实现类都要实现定义的新方法,这就带来了很多不便

接口目前已经逐渐趋势化于抽象类,这是因为抽象类拥有更多的功能,而实现类可以实现多个接口。

静态方法
interface A{
	static void show() {
		System.out.println("这是静态方法");
	}
}

静态方法可以通过 接口名.方法名直接调用

接口中的静态方法不会被继承,也不能通过多态的性质进行访问

默认方法
interface A{

	default void time() {
		System.out.println("这是默认方法");
	}
}

默认方法的优势

  1. 可以让接口更良好的升级,当有新的方法需要增加的时候i,可以减少开发人员的负担,不用在每一个实现类中重写方法,因为默认方法不需要重写就可以通过子类调用
  2. 减少没必要的空实现

如果一个实现类实现了两个接口,并且接口中有同一个静态方法,那么

  1. 继承的父类和实现的接口中有相同签名的方法时,优先使用父类的方法。
  2. 当接口的父接口中也有同样的默认方法时,就近原则调用子接口的方法。
  3. 当实现的多个接口中有相同签名的方法时,必须在实现类中通过重写方法解决冲突问题,否者无法通过编译,在重写的方法中可以通过 接口名.super.方法名(); 的方式显示调用需要的方法。
public class Test {
	public static void main(String[] args) {
		A a = new B();
		a.time();
		
		
		
	}
}

interface A{

	default void time() {
		System.out.println("这是默认方法");
	}
}
interface C extends A{
	default void time() {
		System.out.println("这是重写后的默认方法");
	}
}
 class D {
	public  void time() {
		System.out.println("这是父类方法");
	}
}
class B extends D implements A,C{

}

Lambda

Lambda表达式时Java8的新特性,可以支持函数式编程,个人感觉其作用主要就是简化代码,但需要函数式编程的思想,如果不是很有必要,用原来的方法也可以,不必学习Lambda,因为这并不会影响你写代码

首先要明白,方法不可以单独存在,而函数更不能单独存在。

行为参数化

作为一个开发人员,要明白需求不是固定的,这要取决于甲方爸爸,例如

	public int time(int a) {
		int sum = 0;
		for(int i = 1;i <= a;i++) {
			sum+=i;//核心执行代码
		}
		return sum;
	}
	public int show(int a) {
		int sum = 0;
		for(int i = 1;i <= a;i++) {
			sum = (int) (sum == 0?sum+=1:sum*i);//核心执行代码
		}
		return sum;
	}  

这两个方法都是甲方的需求,但还有可能还会有更多类似的需求,而我们并不知道最终需求是哪个一个,那么就需要都写出来

但仔细观察就会发现,这两个方法除了方法名和核心行为代码不同以外,其他都相同

那么,其实我们就可以传一个核心行为到同一个方法中,这样就可以通过传入的不同行为实现不同的方法。

	public int top(int a,核心行为代码) {
		int sum = 0;
		for(int i = 1;i <= a;i++) {
			核心行为代码
		}
		return sum;
	} 

这种方法就是行为参数化,将核心行为操作抽象变成一个参数

需要注意的是,方法名只是一个标识符,通过标识符来确定调用的是哪一个方法,一个方法最关键的就是行为的操作代码

我们知道,在Java中是不允许有独立代码存在的-----核心行为代码,所以必须要依托于一个类。

public class Test {
	public int time(int a) {
		int sum = 0;
		for(int i = 1;i <= a;i++) {
			sum+=i;
		}
		return sum;
	}
	public int show(int a) {
		int sum = 0;
		for(int i = 1;i <= a;i++) {
			sum = (int) (sum == 0?sum+=1:sum*i);
		}
		return sum;
	}  
	
	public int calculate(int a,CoreBehavior c) {
		int sum = 0;
		for(int i = 1;i <= a;i++) {
			sum = c.result(sum,a);
		}
		return sum;
	}

	public static void main(String[] args) {
		new Test().calculate(10, new CoreBehavior() {
			//求和
			@Override
			public int result(int a,int b) {
				a += b;
				return a;
			}
		});
	}
}

interface CoreBehavior{
//核心行为
	int result(int a,int b);
}

这就是将核心行为抽出来,这相当于之前是简化了不少代码,

但其实我们发现,每次调用还是需要编写较多的代码

每次我们都需要new对象的操作,还有对result方法的声明,但我们其实真正关心的其实就是三部分

  • 方法的参数列表
  • 方法中的核心操作代码
  • 方法的返回类型

而函数式编程就是将创建匿名对象的过程,变成一个计算求值的过程,那么这个求值的表达式就是我们所谓的函数式编程,也就是所谓的Lambda表达式

public static void main(String[] args) {
		new Test().calculate(10,(a,b)->a+=b);
	}
//其中new Test().calculate(10,(a,b)->a+=b);是下面Lambda表达式更进一步的简写
//new Test().calculate(10,(int a,int b)->{
//			return a+=b;
//		});
  • 其中()标识参数列表,
  • ->后面跟的是函数主题
  • {}函数主体,表达式的返回值,由这个函数主体中的代码来决定

Lambda表达式在Java中存在的意义就是作为一个接口的实现类对象

这个接口必须是函数式接口:该接口中有且仅有一个抽象方法,允许默认方法和静态方法的存在

针对于函数式接口,java8新增了一个注解@FunctionalInterface,用来检查该接口是不是一个函数式接口,如果不是,编译就会报错

函数式接口中,抽象方法常见的几种情况

  1. 抽象方法无参,无返回值

    @FunctionalInterface
    interface CoreBehavior{
    	void result();
    }
    public class Test {
    	public static void main(String[] args) {
    		//标准语法{}中放执行语句
    		CoreBehavior c = ()->{};
    		//如果只有一行执行语句
    		c = ()->System.out.println();
    	}
    }
    
  2. 抽象方法有参无返回值

    
    @FunctionalInterface
    interface CoreBehavior{
    	void result(int a);
    }
    @FunctionalInterface
    interface Core{
    	void result(int a,String s);
    }
    public class Test {
    	public static void main(String[] args) {
    		//一个参数
    		//标准语法{}中放执行语句
    		CoreBehavior c = (int a)->{};
    		//简化
    		c = (a)->{};
            //再简化,多个参数不可以这样写
            c = a ->{};
    		//只有一行语句
    		c = a->System.out.println(a);
    		//多个参数
    		//标准语句
    		Core o = (int a,String s)->{};
    		//简化
    		o = (a,s)->{};
    		//一行语句
    		o = (a,s)->System.out.println(a+s);
    	}
    }
    
  3. 抽象方法无参,有返回值

    @FunctionalInterface
    interface Core{
    	int result();
    }
    public class Test {
    	public static void main(String[] args) {
    		//标准语法
    		Core c = ()->{
    			int a =1;
    			return a;
    		};
    		//简化,只有一行语句的时候 不写return
    		c = ()->1;
    	}
    }
    
  4. 抽象方法有参,有返回值

    @FunctionalInterface
    interface CoreBehavior{
    	String  result(int a,String s);
    }
    @FunctionalInterface
    interface Core{
    	int result(int a);
    }
    public class Test {
    	public static void main(String[] args) {
    		//一个参数
    		//标准语法
    		Core c = (int a)->{
    			a++;
    			return a;
    		};
    		//简化,只有一行语句 不写return
    		c = a->a;
    		//多个参数
    		//标准语法
    		CoreBehavior o = (int a,String s)->{
    			String b = a+s;
    			return b;
    		};
    		//简化,只有一行语句 不写return
    		o = (a,s)->a+s;
    	}
    }
    

    在Lambda表达式中,参数列表里里面的参数可以不写类型,JVM会自动推断。

@FunctionalInterface
interface CoreBehavior{
	String  result(String s);
}
@FunctionalInterface
interface Core{
	int result(int a,String s);
}
public class Test {
	public void test1(CoreBehavior c) {
		System.out.println(c.result("1"));
	}
	public void test1(Core c) {
		System.out.println(c.result(1,""));
	}
	
	public static void main(String[] args) {
        //调用的是CoreBehavior里面的方法
		new Test().test1((a)->a);
	}
}

当然也会有其他问题

@FunctionalInterface
interface CoreBehavior{
	String  result(String s);
}
@FunctionalInterface
interface Core{
	int result(int a);
}
public class Test {
	public void test1(CoreBehavior c) {
		System.out.println(c.result("1"));
	}
	public void test1(Core c) {
		System.out.println(c.result(1));
	}
	public static void main(String[] args) {
		new Test().test1(a->a);//这行会编译报错,因为两个方法都满足
		new Test().test1((Core)a->a);//进行类型转化就可以,明确调用的是哪个方法
	}
}

还有一点需要注意的是

在Java8中,被匿名内部类,局部内部类,Lambda表达式访问的局部变量要么是一个常量,要么看起来像一个常量(只进行一次赋值)

06-06 542
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值