一、重点知识
注解并无主动功能,主要功能就是给类和类的组成做标记,让编译器检查
RetentionPolicy.CLASS是默认生命周期,没有被@Retention修饰的注解的生命周期都是这种策略。
接口中default方法只能让实现类用
static 定义的方法只能给接口用
接口中只有一个抽象方法时,才可以用lambda表达式简写,这样的接口我们称为函数式接口
只有有提示的时候编译器才能给lambda表达式补全
函数接口实现匿名内部类的简写形式就是lambda表达式
lambda表达式不能调用接口中的默认方法
异常最重要的是名称,处理都以异常名为准
二、重点问题
注解部分重点内容:
1、什么是注解,注解的作用
2、如何自定义一个注解
3、三种重要的元注解
@target规定了注解的使用位置 @retention 规定注解的生命周期 @Repeatable 定义重复注解
4、注解在实际中如何通过反射调用
三课堂知识
注解
- 定义:
- 注解就是给代码中的某个成员做一个标记
- 至于能不能发挥作用,主要看检测这个标记的功能
- 自定义注解
- 写一个类, @interface
- 元注解 : 用来给标记注解
- @Target : 当前定义的注解以后可以使用在什么位置
- @Retention : 当前注解保留到什么时候
一. default关键字
-
定义
- 1.8中允许我们给接口添加一个非抽象的方法实现, 在方法使用default关键字就可以了,这个特征又叫做拓展方法
-
演示
public interface MyInterface { //使用default的关键字 public default void method(){ System.out.println("你好...."); } }
-
注意事项
- 我们都知道, java之所以支持多实现就是应为接口中没有具体的逻辑代码, 不会造成冲突的问题, 那么1.8之后我们可以在接口中编写具体的逻辑代码了,那么多实现的时候会冲突吗 ?
- 肯定会冲突的,所以为了解决这个问题, 编译器要求如果多实现的时候出现了相同名称的非抽象方法的话,子类就必须重写这个方法
-
多实现
public class Demo implements MyInterface,MyInterface2{ @Override public void method() { System.out.println("子类必须重写多个接口中相同名称的非抽象方法"); MyInterface.super.method(); } }
二. 接口中的静态方法
-
定义
- 在接口中定义一个静态的方法, 可以有具体的代码实现
-
演示
public interface MyInterface { //静态方法 只能接口自己使用 //接口中的静态方法权限必须是public的, 默认加上public static void method3(){ System.out.println("我是接口中的静态方法"); } }
-
注意事项
- 子类无法使用接口中的静态方法
- 接口中的静态方法的权限必须是公共的,可以不写,默认是公共的
三. lambda表达式
-
定义
- 一种简写形式,格式精简, 很酷
- 每一个lambda的表达都对应一个类型,通常是接口类型的
- 适用于函数式接口(只有一个抽象方法的接口)
-
格式
- (参数...) -> {执行代码} 返回一个可用的对象
- 当只有一句代码时,大括号可以省略, 不建议省略
-
演示
public static void main(String[] args) { List<String> list = Arrays.asList("hh","dd","ni","kk"); //之前的写法 Collections.sort(list,new Comparator<String>() { public int compare(String o1, String o2) { return o1.compareTo(o2); } }); //lambda表达式的写法 Collections.sort(list, (String a,String b)->{ return a.compareTo(b); }); System.out.println(list); }
-
方法的引用
- 使用 : : 来引用一个类的方法
public interface Doing<K,T> { public T doing(K k); }
public static void main(String[] args) { //调用类中的静态方法来处理接口中方法上的参数 Doing<String, Integer> d = Integer::valueOf; Integer integer = d.doing("123"); System.out.println(integer); }
public static void main(String[] args) { //调用对象的方法 Doing<String, Integer> d = "java"::lastIndexOf; Integer i = d.doing("v"); System.out.println(i); }
-
构造方法的引用
- 用new关键字来代替构造方法
public class Person { String name; Person(String name) { super(); this.name = name; } @Override public String toString() { return "Person [name=" + name + "]"; } }
public static void main(String[] args) { //引用对象的构造方法 Doing<String, Person> d = Person::new; Person person = d.doing("小明"); System.out.println(person); }
-
注意事项
- lambda表达式指向的接口必须和调用的方法的参数一致,也就是说相当于是接口实现类中的方法调用你指向的方法
- lambda表达式中访问外层作用域和老版本的匿名对象的方式很相似, 你可以直接访问标记了final的外层局部变量, 或者示例的字段以及静态变量
- lambda表达式中无法访问接口中的默认方法(就是被default修饰的方法)
四. Stream接口
-
定义
- 表示能应用在一组元素上一次执行的操作序列
- 其实就是找了一个地方将执行了某个方法后剩下的元素存放起来
- 提供了许多操作集合的方法,而且原集合数据不受影响
-
常用的方法
- filter 过滤
- sorted 排序
- map 转化
- match 匹配
- count 计数
-
演示
public static void main(String[] args) { List<String> stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1"); //过滤出以a开头的元素并遍历 stringCollection.stream(). filter((s)->s.startsWith("a")) .forEach(System.out::println);; }
-
并行
- 并行Stream可以在多个线程上同时执行
public static void main(String[] args) { int max = 1000000; List<String> values = new ArrayList<>(max); for (int i = 0; i < max; i++) { //创建随机id UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } long t1 = System.nanoTime(); //获取并行的stream long count = values.parallelStream().sorted().count(); System.out.println(count); long t2 = System.nanoTime(); System.out.println(t2-t1); }
五. Date
-
定义
- java 8 在包java.time下包含了一组全新的时间日期API
-
ZoneId
- 定义时区
public static void main(String[] args) { System.out.println(ZoneId.getAvailableZoneIds()); //获取某个城市的时区 ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Asia/Shanghai"); System.out.println(zone1.getRules()); System.out.println(zone2.getRules()); }
-
LocalTime
- 一个没有时区信息的时间,以设置的时区为准备
public static void main(String[] args) { //获取所有的时区信息 System.out.println(ZoneId.getAvailableZoneIds()); //获取某个城市的时区 ZoneId zone1 = ZoneId.of("Europe/Berlin"); ZoneId zone2 = ZoneId.of("Asia/Shanghai"); LocalTime now1 = LocalTime.now(zone1); LocalTime now2 = LocalTime.now(zone2); //判断时间1以是否在时间2之前 System.out.println(now1.isBefore(now2)); // true //使用ChronoUnit计算两个时间差值 long hoursBetween = ChronoUnit.HOURS.between(now1, now2); long minutesBetween = ChronoUnit.MINUTES.between(now1, now2); System.out.println(hoursBetween); System.out.println(minutesBetween); }
六.其他新特性
- 重复注解
- 可以将参数的名字保留到字节码中
- Nashorn引擎 : jjs , 可以执行js代码
- 移除了FermGen空间,用Metaspace代替
- -XX:MetaSpaceSize与-XX:MaxMetaspaceSize被代替-XX:PermSize与-XX:MaxPermSize
网友评论