java8新特性简单介绍

lambda表达式

public class Client {
  public static void main(String[] args) {
    Arrays.asList("hello", "world").forEach(a -> {
      System.out.println(a);
      System.out.println(a.length());
    });
  }
}

lambda可以看做java的函数式编程,主要有3部分组成,参数列表、符号->、函数体,java本身提供来了一些函数式接口,Function,Consumer,Predicate,Supplier等,我们也可以定义自己的函数式接口。

接口默认方法和静态方法

public class Client {

  public static void main(String[] args) {
    MyList myList = new MyArrayList();
    myList.addAll("hello", "world");
    System.out.println(myList);
    MyList newList = MyList.of("java", "python");
    System.out.println(newList);
  }

// 定义一个接口包含默认方法和静态方法
  interface MyList {
    void add(Object obj);

// 默认方法
    default void addAll(Object... objs) {
      for (Object obj : objs) {
        add(obj);
      }
    }

// 静态方法
    static MyList of(Object... objs) {
      MyList myList = new MyArrayList();
      myList.addAll(objs);
      return myList;
    }
  }

// 接口实现类
  static class MyArrayList implements MyList {

    private List<Object> data = new ArrayList<>();

    @Override
    public void add(Object obj) {
      data.add(obj);
    }

    @Override
    public String toString() {
      return data.toString();
    }
  }
}

默认方法类似于抽象类中的非抽象方法,默认被所有实现类继承,java中的List接口就定义了很多默认方法,如stream方法,静态方法和类中的静态方法类似。

方法引用

public class Client {
  public static void main(String[] args) {
    testConstructorReference();
    testStaticMethodReference();
    testInstanceMethodReference();
    testObjectMethodReference();
  }

// 构造方法引用
  private static void testConstructorReference() {
    Supplier<Date> supplier = Date::new;
    Date date = supplier.get();
    System.out.println(date);
  }
// 静态方法引用
  private static void testStaticMethodReference() {
    List<Integer> list = Arrays.asList(82, 22, 34, 50, 9);
    list.sort(Integer::compare);
    System.out.println(list);
  }
// 实例方法引用
  private static void testInstanceMethodReference() {
    List<Integer> list = Arrays.asList(82, 22, 34, 50, 9);
    Supplier<Integer> supplier = list::size;
    System.out.println(supplier.get());
  }
//对象方法引用
  private static void testObjectMethodReference() {
    BiFunction<List, String, Boolean> function = List::contains;
    Boolean result = function.apply(Arrays.asList("a", "b", "c"), "a");
    System.out.println(result);
  }
}

方法引用一般和lambda表达式一起使用,共有4中类型:

  1. 构造方法引用,语法为Class::new,调用的为无参构造器
  2. 静态方法引用,语法为Class::method
  3. 实例方法引用,语法为instance::method
  4. 对象方法引用,语法为Class::method

重复注解

public class Client {
  public static void main(String[] args) {
    Logs logs = User.class.getAnnotation(Logs.class);
    for (Log log : logs.value()) {
      System.out.println(log.value());
    }
  }

// 使用重复注解
  @Log("hello")
  @Log("world")
  static class User {
  }

// 定义一个注解 Repeatable注解标识重复注解
  @Target(ElementType.TYPE)
  @Retention(RetentionPolicy.RUNTIME)
  @Repeatable(Logs.class)
  @interface Log {
    String value();
  }

// 定义一个注解容器,存放重复注解
  @Target(ElementType.TYPE)
  @Retention(RetentionPolicy.RUNTIME)
  @interface Logs {
    Log[] value();
  }
}

java8新增了一个Repeatable注解来支持重复注解,如果Log注解没有重复使用,只使用了一次,那么Class中只能得到Log注解信息,如果使用多次,那么只能得到Logs注解信息,这是编译器帮我们做的。

Optional

ublic class Client {
  public static void main(String[] args) {
    findUserById(1).ifPresent(System.out::println);
    findUserById(2).ifPresent(System.out::println);
  }

  private static Optional<User> findUserById(int id) {
    if (id == 1) {
      return Optional.of(new User("lisi"));
    } else {
      return Optional.empty();
    }
  }

  @Setter
  @Getter
  @AllArgsConstructor
  @NoArgsConstructor
  @ToString
  static class User {
    private String userName;
  }
}

Optional可以看做一个单容量的容器,可以用来防止空指针异常。

StreamApi

public class Client {
  public static void main(String[] args) {
// 创建一个流
    String lan = Stream.of("java", "javascript", "python", "go", "kotlin")
// 过滤
        .filter(language -> language.length() > 3)
// 排序
        .sorted(Comparator.comparingInt(String::length))
// 收集
        .collect(Collectors.joining("-"));
    System.out.println(lan);
  }
}

streamApi可以看做一连串支持映射、过滤、排序、聚集等操作的集合,通过它我们可以很方便的操作集合,数组等容器。

Date/Time Api

public class Client {
  public static void main(String[] args) {
// 不带时区的时间点
    Instant instant = Instant.ofEpochMilli(System.currentTimeMillis());
    instant = instant.plus(2, ChronoUnit.DAYS);
// 格式化
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 带时区的日期加时间
    LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    System.out.println(localDateTime);
    System.out.println(dateTimeFormatter.format(localDateTime));
  }
}

java8新增了一些关于日期时间的API,来替代之前的Date,Calendar等,新的API都是线程安全的,在易用性上有很大提高。

Base64

public class Client {
  private static String BLOWFISH = "Blowfish";
  private static String SECRET = "test";

  public static void main(String[] args) throws Exception {
// 待处理字符串 数据多才可以看出3种编码的区别
    String source = "abcdefghijklmnopqrstuvwxyz  -+*/_= 1234567890 abcdefghijklmnopqrstuvwxyz";
    byte[] encrypt = encrypt(source);
// 基本编码    
System.out.println(Base64.getEncoder().encodeToString(encrypt));
    System.out.println("===============");
// url安全的编码   
 System.out.println(Base64.getUrlEncoder().encodeToString(encrypt));
    System.out.println("===============");
// 支持MIME类型的编码
    System.out.println(Base64.getMimeEncoder().encodeToString(encrypt));
  }

// 对数据使用Blowfish算法进行加密
  private static byte[] encrypt(String data) throws Exception {
    Cipher cipher = Cipher.getInstance(BLOWFISH);
    SecretKeySpec myskeys = new SecretKeySpec(SECRET.getBytes(), BLOWFISH);
    cipher.init(Cipher.ENCRYPT_MODE, myskeys);
    return cipher.doFinal(data.getBytes());
  }

}

输出结果为

FJV8zIvqmM4xP1GwLJoRATXWE2tCzicKEp8MQtIZE5RalzKc+O4DyccpbGhanbsM+tQ3TG+TIYCMipoUGRcShP09Od+f/h1GBPyLq7fDo6Q=
===============
FJV8zIvqmM4xP1GwLJoRATXWE2tCzicKEp8MQtIZE5RalzKc-O4DyccpbGhanbsM-tQ3TG-TIYCMipoUGRcShP09Od-f_h1GBPyLq7fDo6Q=
===============
FJV8zIvqmM4xP1GwLJoRATXWE2tCzicKEp8MQtIZE5RalzKc+O4DyccpbGhanbsM+tQ3TG+TIYCM
ipoUGRcShP09Od+f/h1GBPyLq7fDo6Q=

java共提供了3中Base64编码

  1. 基本编码,编码表为52个英文字母加上+,/两个字符,结果输出为一行
  2. url安全编码,编码表为52个英文字母加上-,_两个字符,结果输出为一行
  3. MIME类型编码,编码表为52个英文字母加上+,/两个字符,结果输出为多行

猜你喜欢

转载自www.cnblogs.com/strongmore/p/13380118.html