接口中的默认方法
- 接口的定义:
- 接口的作用是定义该类型的实例要具有的功能,也就是必须执行哪些工作,并且不需要关系这些工作具体进行的。
- 接口定义的方法没有方法体的,并且接口不允许定义实例变量。如果一个类实现了这个接口那么必须重写接口的所有方法。
- 类与接口的区别:
- 类中可以定义成员变量,但是接口中不允许存在成员变量
- 接口中所有方法都没有具体实现(Java8以前这种定义是正确的,但是在Java8以后增加了接口的默认实现方法)
- JAVA8中接口的默认方法:
- 默认方法允许接口方法定义默认实现,子类方法不必须实现此方法而就可以拥有该方法的实现。
- 默认方法的优势:
- 默认方法主要的优势是提供了一种扩展接口的方法,而不破坏现有代码。
- 默认方法另外一个优势方法是可选的,子类可以根据不同的需求去重写默认实现。
- 接口中静态方法:
- java8中为接口新增的一项功能:定义一个或者多个静态方法。在调用静态方法是,不需要实现接口,也不需要接口的实例,也就是说调用类的静态方法的方式类型。
- 语法:接口名字.静态方法名。
//函数式接口其实是为了lambda表达式而定义的
//函数式接口完全就是为了实现lambda表达式而提出的
public class TestFunction1 {
public static void main(String[] args) {
Call c = x -> System.out.println(x);
c.applay(8);
}
}
//正确的函数式接口
@FunctionalInterface
interface Call{
//抽象方法
void applay(int i);
//static 不是抽象方法
public static void staticMethod(){
}
//default不是抽象方法
public default void defaultMethod(){
}
//java.lang.Object中的方法不是抽象方法
public boolean equals(Object obj);
}
- Java8的函数式编程主要的4类接口:
- Predicate (判断函数,有输入也有返回,返回true or false)
- Function (有输入也有返回)
- Consumer (类类似与消费者需要传入参数无返回值)
- Supplier (类似与生产者不需要传参数,但是有返回值)
public static void main(String[] args) {
//Predicate (判断函数,有输入也有返回,返回true or false)
Predicate<String> p = (e) -> e.equals("null");
boolean b = p.test("aas");
System.out.println(b);
//Function (有输入也有返回)
//接收一个输入参数,返回一个结果
//参数类型
//T -功能的输入类型
//R -函数的结果类型
Function<Integer,Boolean> f = (t) -> t>3;
System.out.println(f.apply(4));
//Consumer (类类似与消费者需要传入参数无返回值)
Consumer<String> c = (e) -> System.out.println(e);
c.accept("你好Consumer");
//Supplier (类似与生产者不需要传参数,但是有返回值)
Supplier<String> s = () -> {return "www";};
System.out.println(s.get());
//bi = binary 二元的意思 有两个参数的消费者
//代表了接收两个输入参数的操作,并且返回任何结果
BiConsumer<String,Integer> bc = (e,ee) -> System.out.println(e+ee);
bc.accept("aaa", 20);
}
使用Lambda表达式来实现Runnable接口的实例
public static void main(String[] args) {
//1.使用匿名内部类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
}).start();
//2.使用lambda
new Thread(() -> System.out.println("Hello world")).start();
//3.使用匿名内部类
Runnable run = new Runnable() {
@Override
public void run() {
System.out.println("hello world");
}
};
//使用lambda
Runnable run2 = () -> System.out.println("hello world");
//直接调用run方法(没开新线程)
run.run();
run2.run();
}
时间包概述
- Java 的日期与时间 API 问题由来已久,Java 8 之前的版本中关于时间、日期及其他时间日期格式化类由于线程安全、重量级、序列化成本高等问题而饱受批评。Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。
- 新的 java.time 中包含了所有关于时钟(Clock),本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。
- 历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期,API 大大简化了了日期时间和本地化的管理。
- 目前Java8新增了java.time包定义的类表示日期-时间概念的规则,很方便使用;最重要的一点是值不可变,且线程安全。
新的API
- Clock类:
- Clock类提供了访问当前日期和时间的方法。Clock使用时区来访问当前的instant, date和time。Clock类可以替换 System.currentTimeMillis() 和 TimeZone.getDefault()。
- ZoneId(时区)
- 在新API中时区使用ZoneId来表示。时区可以很方便的使用静态方法of()来获取到。时区定义了到UTS时间的时间差,在Instant时间点对象到本地日期对象之间转换的时候是极其重要的。
- LocalTime(本地时间)
- LocalTime 定义了一个没有时区信息的时间。
- LocalDate(本地日期)
- LocalDate 表示了一个确切的日期(eg: 2014-03-11)。该对象值是不可变的,使用方式和LocalTime基本一致。
- LocalDateTime(本地日期时间)
- 表示了具体时间和日期。LocalDateTime和LocalTime还有LocalDate一样,都是不可变的。LocalDateTime提供了一些能访问具体字段的方法。
- zonedDateTime(日期时间和时区信息)
- 使用ZonedDateTime,它保存有ISO-8601日期系统的日期和时间,而且有时区信息。
- Duration类
- Duration持有的时间精确到纳秒。很容易计算两个日期中间的差异。
注意:Date类增加一个新的方法toInstant(),可以将Date转化成新实例,这样就可以做到将Date切换到新的API。
public static void main(String[] args) throws InterruptedException {
//相当于System.currentTimeMillis()
Clock clock = Clock.systemDefaultZone();//获取系统默认时区
System.out.println("系统时间日期"+clock.instant());
System.out.println("时间毫秒:"+clock.millis());
final Clock clock2 = Clock.systemUTC();//获取系统时钟,并将时间转换成使用UTC时区的日期和时间
System.out.println("系统时间日期"+clock2.instant());
System.out.println("时间毫秒:"+clock2.millis());
//ZoneId(时区)
Set<String> set = ZoneId.getAvailableZoneIds();//获取可用区域标识集的集合
Iterator<String> iterator = set.iterator();
iterator.forEachRemaining(System.out::println);
Clock clock3 = Clock.system(ZoneId.of("Europe/Paris"));
System.out.println("系统时间日期"+clock3.instant());
System.out.println("时间毫秒:"+clock3.millis());
//now() 从系统时钟中获取当前时刻
Clock clock4 = Clock.fixed(Instant.now(), ZoneId.of("Asia/Shanghai"));
System.out.println("时间毫秒:"+clock4.millis());
Thread.sleep(1000);
System.out.println(clock4.millis());//不变 时钟在哪一个点不动
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(clock4.millis());
System.out.println(format);
//Date类增加一个新的方法toInstant(),可以将Date转化成新实例,这样就可以做到将Date切换到新的API。
//Instant类也可以用来创建老的Date对象
Instant instant = clock4.instant();
Date from = Date.from(instant);
System.out.println(from);
Clock clock4 = Clock.systemDefaultZone();
LocalDate now = LocalDate.now();
LocalDate now2 = LocalDate.now(clock5);
System.out.println(now);
System.out.println(now2);
//Duration类 获取时间差
LocalDateTime from = LocalDateTime.of(2014, Month.APRIL, 16, 0, 0,0);
LocalDateTime to = LocalDateTime.of(2015, Month.APRIL, 16, 23, 59,59);
Duration between = Duration.between(from, to);
System.out.println(between.toDays());
System.out.println(between.toHours());
//这个例子用于计算2014年4月16好和2015年4月16日之间的天数和小时数
}