jdk1.8 的新特性
1.default关键字
在java里面,我们通常都是认为接口里面是只能有抽象方法,不能有任何方法的实现的,那么在jdk1.8里面打破了这个规定,引入了新的关键字default,通过使用default修饰方法,可以让我们在接口里面定义具体的方法实现
public interface TestJdkCharacter_Default {
/**
* 普通接口
*/
String strTest(String str);
/**
* default关键字
*/
default String strTest2() {
return "default关键字";
}
}
其实这么定义一个方法的主要意义是定义一个默认方法,也就是说这个接口的实现类实现了这个接口之后,不用实现这个default修饰的方法,也可以直接调用
/**
* 测试JDK1.8的特性
* @author Administrator
*
*/
public class TestJdkCharacter implements TestJdkCharacter_Default {
@Override
public String strTest(String str) {
// TODO Auto-generated method stub
return null;
}
/**
* JDK新特性 1、default关键字
*/
public static void main(String[] args) {
String strTest2 = new TestJdkCharacter().strTest2();
System.err.println(strTest2);
}
}
那么比如说jdk的集合List里面增加了一个sort方法,如果定义为一个抽象方法,其所有的实现类如arrayList,LinkedList等都需要对其添加实现,现在用default定义一个默认的方法之后,其实现类可以直接使用这个方法了,
好处就是: 不管是开发还是维护项目,都会大大简化代码量。
2.Lambda 表达式
Lambda表达式是jdk1.8里面的一个重要的更新,这意味着java也开始承认了函数式编程,并且尝试引入其中。
先来体验一下lambda最直观的优点:简洁代码
/**
* 测试JDK1.8的特性
* @author Administrator
*
*/
public class TestJdkCharacter {
public static void main(String args[]){
List<String> names1 = new ArrayList<String>();
names1.add("Google ");
names1.add("Runoob ");
names1.add("Sina ");
names1.add("Taobao ");
names1.add("Baidu ");
List<String> names2 = new ArrayList<String>();
names2.add("Google ");
names2.add("Runoob ");
names2.add("Taobao ");
names2.add("Baidu ");
names2.add("Sina ");
TestJdkCharacter tester = new TestJdkCharacter();
System.out.println("使用 Java 7 语法: ");
tester.sortUsingJava7(names1);
System.out.println(names1);
System.out.println("使用 Java 8 语法: ");
tester.sortUsingJava8(names2);
System.out.println(names2);
}
/**
* 升序排的话就是第一个参数.compareTo(第二个参数);
* 降序排的话就是第二个参数.compareTo(第一个参数);
*/
// 使用 java 7 排序
private void sortUsingJava7(List<String> names){
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
});
}
// 使用 java 8 排序
private void sortUsingJava8(List<String> names){
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
}
}
什么是函数式编程,引用廖雪峰先生的教程里面的解释就是说:函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
前置 | 语法 |
无参数无返回值 | () -> System.out.println(“Hello WOrld”) |
有一个参数无返回值 | (x) -> System.out.println(x) |
有且只有一个参数无返回值 | x -> System.out.println(x) |
有多个参数,有返回值,有多条lambda体语句 | (x,y) -> {System.out.println(“xxx”);return xxxx;}; |
有多个参数,有返回值,只有一条lambda体语句 | (x,y) -> xxxx |
函数也是一等公民了,在java里面一等公民有变量,对象,那么函数式编程语言里面函数也可以跟变量,对象一样使用了,也就是说函数既可以作为参数,也可以作为返回值了 如下:
public static void main(String[] args) {
List<String> li =Arrays.asList("aaa","fsa","ser","eere");
List<String> list = testLamda2(li);
for (String string : list) {
System.out.println(string);
}
}
//这是常规的Collections的排序的写法,需要对接口方法重写
public static List<String> test1(List<String> list){
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
return list;
}
//这是带参数类型的Lambda的写法
public static List<String> testLamda1(List<String> list){
Collections.sort(list, (Comparator<? super String>) (String a,String b)->{
return b.compareTo(a);
}
);
return list;
}
//这是不带参数的lambda的写法
public static List<String> testLamda2(List<String> list){
Collections.sort(list, (a,b)->b.compareTo(a)
);
return list;
}
可以看到不带参数的写法一句话就搞定了排序的问题,所以引入lambda表达式的一个最直观的作用就是大大的简化了代码的开发,像其他一些编程语言Scala,Python等都是支持函数式的写法的。当然,不是所有的接口都可以通过这种方法来调用,只有函数式接口才行,jdk1.8里面定义了好多个函数式接口,我们也可以自己定义一个来调用
3、函数式接口
定义:“函数式接口”是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。jdk1.8提供了一个@FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。
@FunctionalInterface
public interface TestJdkCharacter_Default {
/**
* 普通接口
*/
String strTest(String str);
/**
* 只能写一个抽象方法 否则编译报错
* String strTest();
* String strTest(String str);
* String strTest1(String str);
*/
/**
* default关键字
*/
default String strTest2() {
return "default关键字";
}
//default方法可以任意定义
default void strTest() {
}
default void strTest(Integer i) {
}
//static方法也可以定义
static void test4(){
System.out.println("234");
}
static String test4(String str){
System.out.println("234");
return str;
}
}
4.方法与构造函数引用
jdk1.8提供了另外一种调用方式::,当 你 需 要使用 方 法 引用时 , 目 标引用 放 在 分隔符::前 ,方法 的 名 称放在 后 面 ,即ClassName :: methodName
。例如 ,Apple::getWeight
就是引用了Apple类中定义的方法getWeight。请记住,不需要括号,因为你没有实际调用这个方法。方法引用就是Lambda表达式(Apple a) -> a.getWeight()
的快捷写法
4.1
@FunctionalInterface
public interface TestConverT<T,F> {
F Conver(T t);
}
以::形式调用。测试
/**
* 测试 方法与构造函数引用
* @param args
*/
public static void main(String[] args) {
TestConverT<String, String> tt= String ::valueOf;
String string = tt.Conver("函数接口引用");
System.out.println(string);
}
4.2 对于构造方法也可以这么调用。
定义一个Bean
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
/**
* 必须给一个构造方法
* @param name
* @param age
*/
public User(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
}
在定义一个接口
public interface UserFactory {
User get(String name ,Integer age);
}
User::new就是调用了User的构造方法,Java编译器会自动根据UserFactory.get方法的签名来选择合适的构造函数。
/**
* 测试 方法与构造函数引用
* @param args
*/
public static void main(String[] args) {
UserFactory u= User :: new ;
User user = u.get("zhanhsan", 23);
System.out.println(user.getName()+"---"+user.getAge());
}
还没有测完 没有时间在更新