MyInterfaceImpl myInterface = new MyInterfaceImpl();
myInterface.abstractMethod();
myInterface.defaultMethod();
MyInterface.staticMethod();
4、函数式接口
在Java 8中,函数式接口(Functional Interface)是一个只有一个抽象方法的接口。由于Lambda表达式的引入,函数式接口变得特别有用,因为Lambda表达式可以被用来简洁地表示这些接口的实现。函数式接口是Java实现函数式编程特性的基础。
4.1 自定义函数式接口
Lambda 表达式经常与函数式接口一起使用。定义一个无实现类的接口,接口方法有且只有一个。
@FunctionalInterface
public interface MyService {
void myMethod(String l);
}
MyService myService=(s)-> System.out.println(s);
//或
MyService myService=(s)-> {
System.out.println(s);
};
myService.myMethod("这是一个自定义的函数式接口");
/\* 等价写法 \*/
public interface MyService {
void myMethod(String l);
}
public class MyServiceImpl implements MyService {
@Override
public void myMethod(String l) {
System.out.println(l);
}
}
myService.myMethod("这是一个字符串");
4.2 内置函数式接口
Java 8 中添加了很多内置的函数式接口,比如 Runnable, Callable, Comparator, Predicate 等,路径在java.util.function包中。
类型参数定义及示例:
- < T > 参数输入类型
- < U > 第二个参数输入类型
- < R > 参数输出类型
Predicate< T > 接口
Predicate<Integer> predicate = s -> s>6;
boolean result = predicate.test(7); // true
System.out.println(result);
Function<T, R>接口
Function<Integer, Integer> function = s -> s \* s;
Integer result = function.apply(6); // 36
System.out.println(result);
BiFunction<T, U, R> 接口
BiFunction<Integer,Integer,String> biFunction = (x,y)->{
Integer z=x\*y;
return "计算结果为:"+z;
};
String result =biFunction.apply(3,6);
System.out.println(result); // 计算结果为:18
5、Date/Time API
Java 8引入了全新的Date/Time API,它提供了更简洁、易读和强大的日期时间处理能力。这个新的API是线程安全的,并且是不可变的,这意味着每次对日期时间的修改都会返回一个新的对象,而原始对象则保持不变,路径在java.time包中。以下是Java 8 Date/Time API的一些主要类和接口:
方法 | 说明 | 默认输出格式 |
---|---|---|
LocalDate | 表示没有时区的日期 | 2024-03-27 |
LocalTime | 表示没有时区的时间 | 17:00:23.741 |
LocalDateTime | 表示包含日期和时间的日期时间,没有时区 | 2024-03-27T17:00:23.741 |
ZonedDateTime | 表示包含日期、时间、时区的日期时间 | 2024-03-27T17:00:23.742+08:00[GMT+08:00] |
OffsetTime | 表示带有时区偏移的时间 | 17:00:23.742+08:00 |
OffsetDateTime | 表示带有时区偏移的日期时间 | 2024-03-27T17:00:23.743+08:00 |
Period | 表示年、月、日之间的时间段 | P2024Y1M1D |
Duration | 表示时间量,通常以秒和纳秒为单位 | PT60H |
TemporalAdjuster | 用于调整日期和时间的接口 | / |
ChronoUnit | 枚举类型,表示时间单位,如天、小时、分钟等 | / |
ZoneId | 表示时区ID的类 | / |
ZoneOffset | 表示时区偏移的类 | / |
DateTimeFormatter | 格式化日期时间 | / |
… | … | … |
一些常用方法示例:
//表示没有时区的日期
LocalDate localDate1 =LocalDate.now();
LocalDate localDate2 =LocalDate.of(2024, 1,1);
System.out.println(
"当前日期:"+localDate1.toString()+"\n"+
"设置规定日期:"+localDate2.toString()
);
//格式化日期
DateTimeFormatter dateTimeFormatter1 =DateTimeFormatter.ofPattern("yyyy/MM/dd");
String format1 = localDate1.format(dateTimeFormatter1);
String format2 = localDate1.format(DateTimeFormatter.ISO\_DATE);
System.out.println(
"自定义日期格式:"+format1+"\n"+
"内置日期格式:"+format2
);
//解析字符串为日期
LocalDate parse1 = LocalDate.parse("2024-01-01");
LocalTime parse2 = LocalTime.parse("12:00:00",DateTimeFormatter.ISO\_TIME);
System.out.println(parse1+"\n"+parse2);
//表示没有时区的时间
LocalTime localTime1 =LocalTime.now();
LocalTime localTime2 =LocalTime.of(10,0,0);
System.out.println(
"当前时间:"+localTime1.toString()+"\n"+
"设置规定时间:"+localTime2.toString()
);
//格式化时间
DateTimeFormatter dateTimeFormatter2 =DateTimeFormatter.ofPattern("HH点mm分ss秒");
String format3 = localTime1.format(dateTimeFormatter2);
String format4 = localTime1.format(DateTimeFormatter.ISO\_TIME);
System.out.println(
"自定义时间格式:"+format3+"\n"+
"内置时间格式:"+format4
);
//表示包含日期和时间的日期时间,没有时区
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);
//格式化时间日期
DateTimeFormatter dateTimeFormatter3 =DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String format5 = localDateTime.format(dateTimeFormatter3);
String format6 = localDateTime.format(DateTimeFormatter.ISO\_LOCAL\_DATE\_TIME);
System.out.println(
"自定义时间日期格式:"+format5+"\n"+
"内置时间日期格式:"+format6
);
//表示包含日期、时间、时区的日期时间
ZonedDateTime zonedDateTime =ZonedDateTime.now();
System.out.println(zonedDateTime);
//表示带有时区偏移的时间
OffsetTime offsetTime =OffsetTime.now();
System.out.println(offsetTime);
//表示带有时区偏移的日期时间
OffsetDateTime offsetDateTime =OffsetDateTime.now();
System.out.println(offsetDateTime);
//表示年、月、日之间的时间段
Period period =Period.of(2024,1,1);
System.out.println(period.toString());
//表示时间量,通常以秒和纳秒为单位
Duration duration=Duration.of(60, ChronoUnit.HOURS);
System.out.println(duration);
//用于调整日期和时间的接口
TemporalAdjuster temporalAdjuster =(s)->{
return s;
};
LocalDate localDate = localDate1.plusDays(1);
Temporal temporal = temporalAdjuster.adjustInto(localDate);
System.out.println(temporal.toString());
//枚举类型,表示时间单位,如天、小时、分钟等
ChronoUnit chronoUnit=ChronoUnit.DAYS;
System.out.println(chronoUnit.toString());
//表示时区ID的类
ZoneId zoneId=ZoneId.of("GMT+08:00");
System.out.println(zoneId.toString());
//表示时区偏移的类
ZoneOffset zoneOffset =ZoneOffset.of("+08:00");
System.out.println(zoneOffset.toString());
6、Optional 容器类型
Optional 是 Java 8 引入的一个容器对象,用于表示某个值存在或不存在,而不是传统的 null 值。Optional 提供了一种更优雅和类型安全的方式来处理可能为 null 的值,从而避免了 NullPointerException。当你有一个值可能是 null,并且你想以更清晰、更简洁的方式处理这种情况时,Optional 就非常有用。使用 Optional 可以使你的代码更易于阅读和维护,同时减少处理 null 值时的错误。
/\* 示例 \*/
// 使用 of 方法创建一个包含值的 Optional
Optional<String> optional1 = Optional.of("hello world");
// 使用 ofNullable 方法创建一个可能包含 null 的 Optional
Optional<String> optional2 = Optional.ofNullable(null);
// 创建一个空的 Optional
Optional<String> optional3 = Optional.empty();
System.out.println(
"optional1的值:"+optional1+"\n"+
"optional2的值:"+optional2+"\n"+
"optional3的值:"+optional3
);
/\* 常用方法 \*/
// isPresent() 检查值是否存在
boolean present = optional1.isPresent(); //true
System.out.println(present);
// ifPresent() 如果值存在则执行给定的操作
optional1.ifPresent(s->{
System.out.println("打印:"+s); //打印:hello world
});
// get() 获取值,如果 Optional 为空则抛出 NoSuchElementException
String s1 = optional1.get();
// orElse() 如果值存在则返回它,否则返回提供的默认值
String s2 = optional2.orElse("optional2值为空");
// orElseGet() 如果值存在则返回它,否则使用提供的 Supplier 生成默认值
String s3 = optional3.orElseGet(() -> {
return "optional3值为空";
});
System.out.println(
"s1:"+s1+"\n"+
"s2:"+s2+"\n"+
"s3:"+s3
);
// map() 如果值存在则应用函数并返回新的 Optional,不存在则不执行map()
Optional<Integer> optional4 = optional1.map(String::length);
Optional<Integer> optional5 = optional2.map(String::length);
System.out.println(
"optional4:"+optional4.orElse(-1)+"\n"+
"optional5:"+optional5.orElse(-1)
);
// flatMap() 如果值存在则应用函数并返回结果的 Optional,否则返回空的 Optional
Optional<String> optional6 = optional1.flatMap(s -> {
return Optional.ofNullable("获取optional1的值:" + s);
});
Optional<String> optional7 = optional2.flatMap(s -> {
return Optional.ofNullable("获取optional2的值:" + s);
});
System.out.println(
"optional6:"+optional6.orElse(null)+"\n"+
"optional7:"+optional7.orElse(null)
);
7、Stream API
7.1 Streams流
在Java 8及更高版本中,Stream API 提供了一种新的、函数式的方法来处理集合(如 List、Set 等)。使用 Stream API,你可以轻松地对集合进行各种操作,如过滤、映射、排序、聚合等,而无需显式地编写循环。
方法 | 简要说明 |
---|---|
forEach(Consumer action) | 遍历元素,执行指定的操作 |
peek(Consumer action) | 遍历元素,插入节点调试,不影响原本操作 |
distinct() | 去除重复元素 |
sorted() | 升序排序 |
count() | 计数 |
filter(Predicate predicate) | 过滤出所有符合条件的元素 相当于if |
map(Function mapper) | 将元素转换为特定类型 |
flatMap(Function mapper) | 嵌套map |
IntStream.sum() | 聚合元素 |
boxed() | 将基本数据类型转换为对应的包装类类型 |
limit(long maxSize) | 限制元素数量,设定集合容量 |
skip(long n) | 跳过前N个元素 |
findFirst() | 返回第一个元素 |
findAny() | 返回任意一个元素 |
reduce(BinaryOperator accumulator) | 将所有元素归成一个约定的结果 |
collect(Collector collector) | 收集结果到一个集合中 |
allMatch(Predicate predicate) | 判断是否所有元素符合给定条件 |
anyMatch(Predicate predicate) | 判断是否有元素符合给定条件 |
noneMatch(Predicate predicate) | 判断是否所有元素都不符合给定条件 |
… | … |
/\* 示例 \*/
// forEach 遍历元素,执行指定的操作
List<String> list1 = Arrays.asList("a", "b", "c");
list1.stream().forEach(s-> System.out.println(s));
list1.stream().forEach(System.out::println);
//peek 遍历元素,插入节点调试,不影响原本操作
List<Integer> list = Arrays.asList(1,2,3,4,5);
List<Integer> collect = list.stream()
.filter(s->s>2)
.peek(s -> System.out.println("输出:"+s))
.collect(Collectors.toList());
// distinct 去除重复元素
List<Integer> list2 = Arrays.asList(1, 2, 1, 3);
List<Integer> collect2 = list2.stream().distinct().collect(Collectors.toList());
System.out.println(collect2);
// sorted 升序排序
List<String> list3 = Arrays.asList("a", "l", "c","j");
List<String> collect3 = list3.stream().sorted().collect(Collectors.toList());
System.out.println(collect3);
// count 计数
long count = list3.stream().count();
System.out.println(count);
// filter 过滤出所有符合条件的元素 相当于if
List<Integer> list4 = Arrays.asList(9, 8, 7, 6);
List<Integer> collect4 = list4.stream().filter(s -> s > 6).collect(Collectors.toList());
System.out.println(collect4);
// map 将元素转换为特定类型
List<Integer> list5 = Arrays.asList(1,2,3,4,5);
List<String> collect5 = list5.stream().map(s -> {
return "计算结果为:"+s\*s;
}).collect(Collectors.toList());
System.out.println(collect5);
// flatMap 嵌套map
List<Integer> collect6 = list5.stream().flatMap(s -> {
return list5.stream().filter(a -> a > 4);
}).collect(Collectors.toList());
System.out.println(collect6);
//sum 聚合元素
int sum = list5.stream().mapToInt(s -> s \* 2).sum();
System.out.println("sum:" + sum);
// boxed 将基本数据类型转换为对应的包装类类型
int [] a ={1,2,3,4,5};
List<Integer> collect7 = Arrays.stream(a).boxed().collect(Collectors.toList());
System.out.println(collect7);
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
IntStream intStream = numbers.stream().mapToInt(i -> i); //转成IntStream
Stream<Integer> boxed = intStream.boxed(); //转成Stream<Integer>
List<Integer> collect8 = boxed.collect(Collectors.toList());
System.out.println(collect8);
//limit 限制元素数量,设定集合容量
List<Integer> list9 = Arrays.asList(1,2,3,4,5);
List<Integer> collect9 = list9.stream().limit(2).collect(Collectors.toList());
System.out.println(collect9);
//skip 跳过前N个元素
List<Integer> list10 = Arrays.asList(1,2,3,4,5);
List<Integer> collect10 = list10.stream().skip(3).collect(Collectors.toList());
System.out.println(collect10);
//findFirst() 返回第一个元素,findAny() 返回任意一个元素
List<Integer> list11 = Arrays.asList(1,2,3,4,5);
Optional<Integer> first = list11.stream().findFirst();
Optional<Integer> any = list11.stream().findAny();
System.out.println(
"返回第一个元素:"+first.toString()+"\n"+
"返回任意一个元素:"+any.toString()
);
/\* 将所有元素归成一个约定的结果 \*/
List<Integer> list1 = Arrays.asList(1,2,3,4,5);
Integer reduce1 = list1.stream().reduce(0, (x, y) -> x + y);
System.out.println(reduce1);
List<String > list2 = Arrays.asList("a","b","c");
Optional<String> reduce2 = list2.stream().reduce((x, y) -> x + y);
System.out.println(reduce2.toString());
List<Integer> list3 = Arrays.asList(1,2,3,4,5);
BinaryOperator<Integer> binaryOperator = (x, y)->x\*y;
Integer reduce3 = list3.stream().reduce(1,binaryOperator, binaryOperator);
System.out.println(reduce3);
List<Integer> list = Arrays.asList(1,2,3,4,5);
//allMatch 判断是否所有元素符合给定条件
Predicate<Integer> predicate1 = s -> s>0;
boolean b1 = list.stream().allMatch(predicate1);
System.out.println("判断是否所有元素符合给定条件: "+b1);
//anyMatch 判断是否有元素符合给定条件
Predicate<Integer> predicate2 = s -> s>4;
boolean b2 = list.stream().anyMatch(predicate2);
System.out.println("判断是否有元素符合给定条件: "+b2);
//noneMatch 判断是否所有元素都不符合给定条件
Predicate<Integer> predicate3 = s -> s>10;
boolean b3 = list.stream().noneMatch(predicate3);
System.out.println("判断是否所有元素都不符合给定条件: "+b3);
7.2 Collectors收集器
在Java 8中,Collectors是一个静态工具类,它提供了许多有用的收集器(Collector)实现,用于支持在流(Stream)上的各种聚合操作。这些收集器可以用于收集流中的元素,并生成一个汇总结果或一个汇总结果的集合。以下是一些常用的Collectors收集器方法:
方法 | 简要说明 |
---|---|
toList() | 将流中的元素收集到一个List中 |
toSet() | 将流中的元素收集到一个Set中,去除重复项 |
toCollection(Supplier collectionFactory) | 将流中的元素收集到指定的集合类型中 |
toMap(Function keyMapper,Function valueMapper,BinaryOperator mergeFunction) | 将流中的元素收集到一个Map中 |
counting() | 计算流中元素的数量 |
summingInt(ToIntFunction mapper) | 对流中元素的某个属性进行求和,针对不同类型有不同方法,如:summingDouble,summingLong |
averagingInt(ToIntFunction mapper) | 计算流中元素的某个属性的平均值,针对不同类型有不同方法,如:averagingDouble,averagingLong |
maxBy(Comparator comparator) | 根据指定比较器找到流中最大的元素 |
minBy(Comparator comparator) | 根据指定比较器找到流中最小的元素 |
joining(CharSequence delimiter) | 将流中的元素连接成一个字符串,可以使用指定的分隔符 |
groupingBy(Function classifier) | 根据分类函数对流中的元素进行分组 |
reducing(BinaryOperator op) | 对流中的元素进行规定约定的操作 |
mapping(Function mapper,Collector downstream) | 对流中的元素应用映射函数,并对结果进行收集 |
collectingAndThen(Collector downstream,Function finisher) | 包裹另一个收集器,对其结果进行二次处理 |
… | … |
/\* 示例 \*/
//toList 将流中的元素收集到一个List中
List<Integer> list1 = Arrays.asList(1,2,3,4,5);
List<Integer> collect1 = list1.stream()
.filter(s->s>3)
.collect(Collectors.toList());
System.out.println(collect1);
//toSet 将流中的元素收集到一个Set中,去除重复项
List<Integer> list2 = Arrays.asList(1,2,3,4,5,3);
Set<Integer> collect2 = list2.stream().collect(Collectors.toSet());
System.out.println(collect2);
//toCollection 将流中的元素收集到指定的集合类型中
List<Integer> list3 = Arrays.asList(1,2,3,4,5,3);
HashSet<Integer> collect3 = list3.stream().collect(Collectors.toCollection(HashSet::new));
System.out.println(collect3);
//toMap 将流中的元素收集到一个Map中
List<Person> list4 = Arrays.asList(
new Person("L", 1, 18),
new Person("J", 2, 18),
new Person("A", 1, 30),
new Person("A", 1, 20)
);
//key不鞥重复,针对有重复的情况需要处理 ------ (t,u)->u:当两个key相同时怎么处理
Map<String, Integer> collect4 = list4.stream()
.collect(Collectors.toMap(Person::getName, Person::getAge, (t, u) -> u));
System.out.println(collect4);
//counting 计算流中元素的数量
List<Integer> list5 = Arrays.asList(1,2,3,4,5);
Long collect5 = list5.stream().collect(Collectors.counting());
System.out.println(collect5);
//summingInt 对流中元素的某个属性进行求和,针对不同类型有不同方法,如:summingDouble,summingLong
List<Integer> list6 = Arrays.asList(1,2,3,4,5);
Integer collect6 = list6.stream().collect(Collectors.summingInt(Integer::intValue));
System.out.println(collect6);
//averagingInt 计算流中元素的某个属性的平均值,针对不同类型有不同方法,如:averagingDouble,averagingLong
List<Integer> list7 = Arrays.asList(1,2,3,4,5);
Double collect7 = list7.stream().collect(Collectors.averagingInt(Integer::intValue));
System.out.println(collect7);
//maxBy 根据指定比较器找到流中最大的元素
List<Integer> list8 = Arrays.asList(1,2,3,4,5);
Optional<Integer> collect8 = list8.stream()
.collect(Collectors.maxBy(Comparator.comparingInt(Integer::intValue)));
System.out.println(collect8.get());
//minBy 根据指定比较器找到流中最小的元素
List<Integer> list9 = Arrays.asList(1,2,3,4,5);
Optional<Integer> collect9 = list9.stream()
.collect(Collectors.minBy(Comparator.comparingInt(Integer::intValue)));
System.out.println(collect9.get());
//joining 将流中的元素连接成一个字符串,可以使用指定的分隔符
List<String> list10 = Arrays.asList("a","b","c");
String collect10 = list10.stream().collect(Collectors.joining("/"));
System.out.println(collect10);
//groupingBy 根据分类函数对流中的元素进行分组
List<Person> list11 = Arrays.asList(
new Person("L", 1, 18),
new Person("J", 2, 18),
new Person("A", 1, 30)
);
Map<Integer, List<Person>> collect11 = list11.stream()
.collect(Collectors.groupingBy(Person::getSex));
System.out.println(collect11);
//reducing 对流中的元素进行规定约定的操作
List<Integer> list12 = Arrays.asList(1,2,3,4,5);
Optional<Integer> collect12 = list12.stream().collect(Collectors.reducing(Integer::sum));
System.out.println(collect12.get());
BinaryOperator<Integer> binaryOperator12=(x,y)->x+y;
Optional<Integer> collect13 = list12.stream().collect(Collectors.reducing(binaryOperator12));
System.out.println(collect13.get());
//mapping 对流中的元素应用映射函数,并对结果进行收集
List<Integer> list14 = Arrays.asList(1,2,3,4,5);
List<String> collect14 = list14.stream()
.collect(Collectors.mapping(String::valueOf, Collectors.toList()));
System.out.println(collect14);
Function<Integer,Integer> function15 =(s)->s\*s;
List<Integer> collect15 = list14.stream()
.collect(Collectors.mapping(function15, Collectors.toList()));
System.out.println(collect15);
//collectingAndThen 包裹另一个收集器,对其结果进行二次处理
List<Integer> list16 = Arrays.asList(1,2,3,4,5);
Function<Integer,String> function16 =(s)->{
int l =s\*s;
return "计算它的平方:" + l;
};
String collect16 = list16.stream()
.collect(Collectors.collectingAndThen(Collectors.summingInt(Integer::intValue), function16));
System.out.println(collect16);
7.3 Parallel Streams(扩展)
Java中的Parallel Streams是Java 8引入的一个新特性,它允许你以并行的方式处理数据集合,从而充分利用多核处理器的优势来提高程序的执行效率。通过使用Parallel Streams,你可以将原本顺序执行的任务分解成多个子任务,并在多个线程上同时执行这些子任务,从而加速数据的处理速度。
//示例
List<Long> list = new ArrayList<>();
for (long i = 1; i <=1\_000\_000 ; i++) {
list.add(i);
}
long start1 = System.currentTimeMillis();
List<Long> collect1 = list.stream()
.map(s -> s \* s)
.collect(Collectors.toList());
long end1 = System.currentTimeMillis();
System.out.println(new StringBuffer().append(end1-start1).append("ms"));
long start2 = System.currentTimeMillis();
List<Long> collect2 = list.parallelStream()
.map(s -> s \* s)
.collect(Collectors.toList());
long end2 = System.currentTimeMillis();
System.out.println(new StringBuffer().append(end2-start2).append("ms"));
使用并行流(parallel stream)需要注意:
确保你的任务是可以并行化的,即任务之间没有依赖关系,可以独立执行。
对于大规模数据集,使用并行流可以提高性能。但对于小数据集,顺序流可能更加高效。
避免在并行流中使用阻塞操作,这可能会导致线程阻塞和性能下降。
在使用并行流时,要注意线程安全问题,确保你的代码是线程安全的。
Java 7 常用新特性(补充)
1、二进制字面量
在Java 7中,引入了对二进制字面量的支持。二进制字面量以0b或0B开头,后跟一系列的0和1。
/\* 示例 \*/
int i =0b11111111;
int j =0B00000010;
System.out.println("i: "+i+"\n"+"j: "+j); //i: 255 j: 2
2、数字字面量下划线支持
在Java 7中,引入了对数字字面量下划线的支持。这个特性允许在数字字面量中添加下划线(_)作为分隔符,以提高数字的可读性。这对于表示非常大的数字或者需要分组显示的数字特别有用。这个特性不会影响数字的值,下划线只是作为视觉上的分隔符。下划线可以出现在数字字面量的任何位置,除了数字的首位和末位,以及小数点的前面和后面。这个特性只适用于整数和浮点数的字面量,不适用于十六进制或八进制字面量。此外,虽然下划线可以提高代码的可读性,但过度使用可能会使代码变得难以阅读,因此建议适度使用。
/\* 示例 \*/
int i=1\_000\_000;
double r =3.14\_1\_5\_92\_7;
long l=7\_7\_7\_7L;
System.out.println(i); //1000000
System.out.println(r); //3.1415927
System.out.println(l); //7777
3、switch中使用String
在Java 7之前,switch语句仅支持字节型(byte)、短整型(short)、整型(int)、字符型(char)、枚举(enum)以及从Java 5开始引入的字符串类型(String)。然而,在Java 7中,对于switch语句中使用String类型的支持得到了扩展,允许你在switch语句中直接使用字符串。switch语句对字符串的比较是区分大小写的,switch语句中字符串的比较是通过字符串的equals方法进行的。
/\* 示例 \*/
String a ="List";
switch (a){
case "list":
System.out.println("list");
break;
case "List":
System.out.println("List");
break;
case "set":
System.out.println("set");
break;
default:
System.out.println("default");
}
4、对集合类的语言支持
Java 7 对集合类(Collections)的语言支持主要体现在对泛型实例创建的简化以及"diamond"操作符的引入,它减少了泛型代码中的冗余和错误。
4.1 泛型实例创建的简化
在Java 7之前,当创建一个泛型集合时,通常需要为集合和它的元素类型都指定泛型参数。Java 7中,对于类型推断的改进使得这种指定变得不必要,因为编译器可以根据上下文自动推断类型。
/\* 示例 \*/
//Java 7之前写法
List<String> list1 = new ArrayList<String>();
//Java 7及以后的版本
List<String> list2 = new ArrayList<>();
4.2 "diamond"操作符
"diamond"操作符在其他泛型上下文中得到应用,如方法返回类型、方法参数、构造函数参数等。它使得泛型代码更加简洁,减少了重复的类型参数声明。
/\* 示例 \*/
//Java 7之前写法
List<String> list1 = Arrays.asList(new String[]{"a", "b", "c"});
//Java 7及以后的版本
List<String> list2 = Arrays.asList("a", "b", "c");
/\* asList 源码 \*/
// <T>:表示数组中对象的类,编译器可通过上下文自动推断类型
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
5、自动资源管理
在Java 7中,为了更方便地管理资源(如文件流、数据库连接、网络连接等),引入了自动资源管理(Automatic Resource Management)的概念,这个特性允许开发者在try语句块中声明一个或多个资源,这些资源在try语句块执行完毕后会自动关闭。这避免了手动关闭资源的繁琐操作,并减少了因忘记关闭资源而导致的资源泄露问题。要使用这个特性,资源类必须实现AutoCloseable接口或Closeable接口(Closeable接口是AutoCloseable接口的子接口)。
/\* 示例 \*/
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
在上面的代码中,BufferedReader实现了Closeable接口,因此在try语句块执行完毕后,BufferedReader会自动关闭,无需手动调用br.close()。
6、try-catch多异常捕获
在Java 7及以后的版本中,try-catch语句块支持捕获多个异常类型,这是通过在一个catch块中指定多个异常类型来实现的,这些类型之间用竖线(|)分隔。这种语法允许你在一个catch块中处理多个不同类型的异常,而无需为每个异常类型编写单独的catch块。
/\* 示例 \*/
//当try块中的代码抛出异常时,Java虚拟机(JVM)会检查catch块中列出的异常类型,并找到第一个与抛出的异常类型匹配的catch块。
try {
int i =1/0; // class java.lang.ArithmeticException
String s =null; //class java.lang.NullPointerException
s.indexOf(0);
}catch (ArithmeticException | NullPointerException e){
System.out.println("程序报错:"+e.getClass());
}
7、文件流
在Java 7中,文件流(File Streams)的处理得到了显著改进,特别是通过引入java.nio.file包中的新API。这些新API提供了更简洁、更直观的方式来处理文件I/O操作,同时提供了对文件属性、文件访问权限以及异步文件I/O的更全面支持。
7.1 文件路径(Path)
java.nio.file.Path接口是文件路径的抽象表示。它提供了许多方法来操作路径,如解析、组合、规范化等。Paths类是一个工具类,提供了静态方法来创建Path对象。
/\* 示例 \*/
Path path = Paths.get("C:\\Users\\777\\Desktop","MyPaths.txt");
System.out.println(path); //C:\Users\777\Desktop\MyPaths.txt
7.2 文件属性(FileAttribute)
Java 7引入了FileAttribute接口,它允许你获取和设置文件的各种属性,如创建时间、最后访问时间、文件类型等。
/\* 示例 \*/
Path path = Paths.get("D:\\File","MyPaths.txt");
System.out.println(path);
BasicFileAttributes basicFileAttributes = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println(
"文件创建时间:"+basicFileAttributes.creationTime()+"\n"+
"文件大小"+basicFileAttributes.size()
);
7.3 文件I/O
java.nio.file包中的Files类提供了一组静态方法,用于简化文件I/O操作。以下是一些常见方法:
检查文件路径是否存在
/\* 示例 \*/
Path path = Paths.get("D:\\File","MyPaths.txt");
try{
//检查文件路径是否存在
boolean exists = Files.exists(path);
System.out.println(exists);
}catch (IOException e){
System.out.println(e.getClass());
e.printStackTrace();
}
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/ed66e8230fa3d7e9ecbadb8882cd1d50.png)
![img](https://img-blog.csdnimg.cn/img_convert/67aa744966ceeea3adbb28406242d6d5.png)
![img](https://img-blog.csdnimg.cn/img_convert/2c3c96327ca3dd49626291564cc31e0b.png)
![img](https://img-blog.csdnimg.cn/img_convert/20508b566092a9adccc0a7a0d7ea11c0.png)
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**
es.exists(path);
System.out.println(exists);
}catch (IOException e){
System.out.println(e.getClass());
e.printStackTrace();
}
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中...(img-awnbwDDa-1712872878005)]
[外链图片转存中...(img-FrJ1CyJH-1712872878006)]
[外链图片转存中...(img-bEOaNPBi-1712872878006)]
[外链图片转存中...(img-FVynzo9n-1712872878006)]
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**
<img src="https://img-community.csdnimg.cn/images/fd6ebf0d450a4dbea7428752dc7ffd34.jpg" alt="img" style="zoom:50%;" />