程序员java学习记录

JAVA---注解、jdk1.8新特性

2020-06-06  本文已影响0人  一花一世界yu

一、重点知识

注解并无主动功能,主要功能就是给类和类的组成做标记,让编译器检查

RetentionPolicy.CLASS是默认生命周期,没有被@Retention修饰的注解的生命周期都是这种策略。
接口中default方法只能让实现类用

static 定义的方法只能给接口用

接口中只有一个抽象方法时,才可以用lambda表达式简写,这样的接口我们称为函数式接口

只有有提示的时候编译器才能给lambda表达式补全

函数接口实现匿名内部类的简写形式就是lambda表达式

lambda表达式不能调用接口中的默认方法

异常最重要的是名称,处理都以异常名为准

二、重点问题

注解部分重点内容:

1、什么是注解,注解的作用

2、如何自定义一个注解

3、三种重要的元注解

@target规定了注解的使用位置 @retention 规定注解的生命周期 @Repeatable 定义重复注解

4、注解在实际中如何通过反射调用

三课堂知识

注解

  1. 定义:
    • 注解就是给代码中的某个成员做一个标记
    • 至于能不能发挥作用,主要看检测这个标记的功能
  2. 自定义注解
    • 写一个类, @interface
    • 元注解 : 用来给标记注解
      • @Target : 当前定义的注解以后可以使用在什么位置
      • @Retention : 当前注解保留到什么时候

一. default关键字

  1. 定义

    • 1.8中允许我们给接口添加一个非抽象的方法实现, 在方法使用default关键字就可以了,这个特征又叫做拓展方法
  2. 演示

    public interface MyInterface {
     //使用default的关键字
     public default void method(){
         System.out.println("你好....");
     }
    }
    
  3. 注意事项

    • 我们都知道, java之所以支持多实现就是应为接口中没有具体的逻辑代码, 不会造成冲突的问题, 那么1.8之后我们可以在接口中编写具体的逻辑代码了,那么多实现的时候会冲突吗 ?
    • 肯定会冲突的,所以为了解决这个问题, 编译器要求如果多实现的时候出现了相同名称的非抽象方法的话,子类就必须重写这个方法
  4. 多实现

    public class Demo implements MyInterface,MyInterface2{
    
     @Override
     public void method() {
         System.out.println("子类必须重写多个接口中相同名称的非抽象方法");
            MyInterface.super.method();
     }
    
    }
    

二. 接口中的静态方法

  1. 定义

    • 在接口中定义一个静态的方法, 可以有具体的代码实现
  2. 演示

    public interface MyInterface {
     
     //静态方法 只能接口自己使用
     //接口中的静态方法权限必须是public的, 默认加上public
     static void method3(){
         System.out.println("我是接口中的静态方法");
     }
    }
    
  3. 注意事项

    • 子类无法使用接口中的静态方法
    • 接口中的静态方法的权限必须是公共的,可以不写,默认是公共的

三. lambda表达式

  1. 定义

    • 一种简写形式,格式精简, 很酷
    • 每一个lambda的表达都对应一个类型,通常是接口类型的
    • 适用于函数式接口(只有一个抽象方法的接口)
  2. 格式

    • (参数...) -> {执行代码} 返回一个可用的对象
    • 当只有一句代码时,大括号可以省略, 不建议省略
  3. 演示

    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);
    
    }
    
  4. 方法的引用

    • 使用 : : 来引用一个类的方法
    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);
    }
    
  5. 构造方法的引用

    • 用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);
    }
    
  6. 注意事项

    • lambda表达式指向的接口必须和调用的方法的参数一致,也就是说相当于是接口实现类中的方法调用你指向的方法
    • lambda表达式中访问外层作用域和老版本的匿名对象的方式很相似, 你可以直接访问标记了final的外层局部变量, 或者示例的字段以及静态变量
    • lambda表达式中无法访问接口中的默认方法(就是被default修饰的方法)

四. Stream接口

  1. 定义

    • 表示能应用在一组元素上一次执行的操作序列
    • 其实就是找了一个地方将执行了某个方法后剩下的元素存放起来
    • 提供了许多操作集合的方法,而且原集合数据不受影响
  2. 常用的方法

    • filter 过滤
    • sorted 排序
    • map 转化
    • match 匹配
    • count 计数
  3. 演示

    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);;
    }
    
  4. 并行

    • 并行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

  1. 定义

    • java 8 在包java.time下包含了一组全新的时间日期API
  2. 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());
    }
    
  3. 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);
    }
    

六.其他新特性

  1. 重复注解
  2. 可以将参数的名字保留到字节码中
  3. Nashorn引擎 : jjs , 可以执行js代码
  4. 移除了FermGen空间,用Metaspace代替
    • -XX:MetaSpaceSize与-XX:MaxMetaspaceSize被代替-XX:PermSize与-XX:MaxPermSize
上一篇下一篇

猜你喜欢

热点阅读