java8新特性(一) lambda表达式

1、小试牛刀

   

package org.chen.study;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class SwingTest {
	public static void main(String[] args) {
		JFrame jFrame = new JFrame("this is title");
		JButton jButton = new JButton("this is button");
		// 为jButton添加事件
		//在1.8之前我们的写法
//		jButton.addActionListener(new ActionListener() {
//			@Override
//			public void actionPerformed(ActionEvent e) {
//				System.out.println("hello world");
//			}
//		});
		
		//1.8引入lambda表达式
		jButton.addActionListener(e -> {
			System.out.println("hello world");
			System.out.println("package");
			});
		
		jFrame.add(jButton);
		jFrame.pack();
		jFrame.setVisible(true);
		jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}

在lambda表达式中e的类型我们并没有定义,这里是根据java类型推断机制进行定义的,当然你也可以显示的显示e的类型

jButton.addActionListener((ActionListener) e -> {
			System.out.println("hello world");
			System.out.println("package");
			});

2、函数式接口

package org.chen.study;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class ConsumerTest {
	public static void main(String[] args) {
		List<Integer> ints = Arrays.asList(new Integer[]{2,2,23,4,5});
		
		//for循环
		for(int i = 0; i < ints.size(); i++){
			System.out.println(ints.get(i));
		}
		
		System.out.println("-----------------");
		
		//foreach循环
		for (Integer integer : ints) {
			System.out.println(integer);
		}
		
		System.out.println("-----------------");
		
		//Consumer
		ints.forEach(new Consumer<Integer>() {
			@Override
			public void accept(Integer t) {
				System.out.println(t);
			}
		});
		
		System.out.println("------------------");
		
		//利用lambda表达式简化consumer
		ints.forEach(action -> System.out.println(action));
	}
}

在上面的例子中,我么用到Consumer类,我们进入这个类中可以看见

/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.util.function;

import java.util.Objects;

/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

可以看见Consumer是一个接口,而且这个接口加了一个注解@FunctionalInterface。这个注解声明这个接口是个函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

 

@FunctionalInterface源码

/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang;

import java.lang.annotation.*;

/**
 * An informative annotation type used to indicate that an interface
 * type declaration is intended to be a <i>functional interface</i> as
 * defined by the Java Language Specification.
 *
 * Conceptually, a functional interface has exactly one abstract
 * method.  Since {@linkplain java.lang.reflect.Method#isDefault()
 * default methods} have an implementation, they are not abstract.  If
 * an interface declares an abstract method overriding one of the
 * public methods of {@code java.lang.Object}, that also does
 * <em>not</em> count toward the interface's abstract method count
 * since any implementation of the interface will have an
 * implementation from {@code java.lang.Object} or elsewhere.
 *
 * <p>Note that instances of functional interfaces can be created with
 * lambda expressions, method references, or constructor references.
 *
 * <p>If a type is annotated with this annotation type, compilers are
 * required to generate an error message unless:
 *
 * <ul>
 * <li> The type is an interface type and not an annotation type, enum, or class.
 * <li> The annotated type satisfies the requirements of a functional interface.
 * </ul>
 *
 * <p>However, the compiler will treat any interface meeting the
 * definition of a functional interface as a functional interface
 * regardless of whether or not a {@code FunctionalInterface}
 * annotation is present on the interface declaration.
 *
 * @jls 4.3.2. The Class Object
 * @jls 9.8 Functional Interfaces
 * @jls 9.4.3 Interface Method Body
 * @since 1.8
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

-------------------------------------------------------------------------

我们自定义一下函数式接口

package org.chen.study;

@FunctionalInterface
public interface MyFunctionalInterface {
	
}

这是编辑器提示错误了 

提示说的很清楚 我们的接口不是一个函数式接口

我们至少可以得出一个结果:函数接口必须要有抽象方法。

这样我们就定义了一个函数接口

我们继续添加抽象方法

又出现错误信息了

我们可以大致推测出 函数式接口不能有两个抽象方法。

在看看下面的例子

我们添加了一个toString()方法,编辑器并没有报错

我们知道toString()方法是继承自Object对象的,那我们可以知道如果重写了java.lang.Object类的方法,那么这个方法不计入抽象方法数的。

再看看下面的例子

这里也是没有报错的。

这个是java8的新特性(接口中的默认方法),后面会说到。

在上面的源码注解中也说的很详细了。

 

 

在java中lambda表达式是对象,而不是函数;

我们看看下面的例子来体会一下:

package org.chen.study;

public class LambdaObject {
	public static void main(String[] args) {
		LambdaObject lambdaObject = new LambdaObject();
		lambdaObject.test(() -> System.out.println("efg"));
	}
	
	public void test(MyFunctionalInterface myFunctionalInterface){
		myFunctionalInterface.test();
	}
}

这里我们运用了我们自定义的函数式接口MyFunctionalInterface。

我们上面说了lambda表达式在java中是对象,那就可以这么做

package org.chen.study;

public class LambdaObject {
	public static void main(String[] args) {
//		LambdaObject lambdaObject = new LambdaObject();
//		lambdaObject.test(() -> System.out.println("efg"));
		MyFunctionalInterface myFunctionalInterface = () -> {};
		System.out.println(myFunctionalInterface.getClass());
		System.out.println(myFunctionalInterface.getClass().getSuperclass());
		System.out.println(myFunctionalInterface.getClass().getInterfaces()[0]);
	}
	
	public void test(MyFunctionalInterface myFunctionalInterface){
		myFunctionalInterface.test();
	}
}

在上面,我们将lambda表达式赋值给MyFunctionInterface对象。我们看到这个对象的一些信息。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值