❶ java里怎么让2个FOR循环并发同时执行
不能在同一个方法内并发运行两个for循环,因为在方法体内是顺序执行的,前一个for不跳出,后一个for是不能执行的。
如果想要并发执行,需要使用Thread类,详情可以去看关于java线程的知识。
❷ 求 Java SE Development Kit8(jdk8)下载32/64位 8u144
软件介绍:
jdk8的全称为Java SE Development Kit8,是运行整个Java的核心,它内置一堆Java工具和Java基础的类库(rt.jar)以及Java运行环境(Java Runtime Envirnment),如果想要在电脑上运行Java程序就必须安装ava SE Development Kit,才能保证程序的正常使用。
所需工具:点击下载 Java SE Development Kit8(jdk8) 8u144
jdk8环境变量配置教程
1、下载软件压缩包文件,点击你电脑系统向对应的程序“jdk-8u144-windows-x64.exe(64位)或者jdk-8u144-windows-i586.exe(32位)”。
2、程序会自动安装JRE程序,选择目录即可
3、直到jdk8下载安装完毕,点击“关闭”按钮即可,如下图所示:
4、安装完JDK后配置环境变量,计算机→属性→高级系统设置→高级→环境变量
5、系统变量→新建 JAVA_HOME 变量
变量值填写jdk的安装目录(本人是 C:Program FilesJavajdk1.8.0_144)
6、系统变量→寻找 Path 变量→编辑
在变量值最后输入 %JAVA_HOME%in;%JAVA_HOME%jrein;
(注意原来Path的变量值末尾有没有;号,如果没有,先输入;号再输入上面的代码)
8、检验是否配置成功 运行cmd 输入 java -version (java 和 -version 之间有空格)若如图所示 显示版本信息 则说明安装和配置成功。
功能介绍
JDK的最重要命令行工具:
1、java: 启动JVM执行class
2、javac: Java编译器
3、jar: Java打包工具
4、javadoc: Java文档生成器
这些命令行必须要非常非常熟悉,对于每个参数都要很精通才行。对于这些命令的学习,JDK Documentation上有详细的文档。
从初学者角度来看,采用JDK开发Java程序能够很快理解程序中各部分代码之间的关系,有利于理解Java面向对象的设计思想。JDK的另一个显着特点是随着Java (J2EE、J2SE以及J2ME)版本的升级而升级。但它的缺点也是非常明显的就是从事大规模企业级Java应用开发非常困难,不能进行复杂的Java软件开发,也不利于团体协同开发。
Java语言恐怕是稳居网路应用程序语言的首选了,这都要归功于它高度的安全性以及跨平台的特性,几乎在目前所有的电脑平台上您都可以见得到Java的芳踪。过去很可能会有不少人抱怨Java虽然有着相当不错的跨平台以及安全防护等特性,但是它的执行速度远远不及C++等各种传统惯用的程序语言。
jdk8新特性
一、Lambda表达式
1、Lambda表达式可以说是Java 8最大的卖点,她将函数式编程引入了Java。Lambda允许把函数作为一个方法的参数,或者把代码看成数据。
2、一个Lambda表达式可以由用逗号分隔的参数列表、–>符号与函数体三部分表示。例如:
Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) );
3、为了使现有函数更好的支持Lambda表达式,Java 8引入了函数式接口的概念。函数式接口就是只有一个方法的普通接口。java.lang.Runnable与java.util.concurrent.Callable是函数式接口最典型的例子。为此,Java 8增加了一种特殊的注解@FunctionalInterface:
二、接口的默认方法与静态方法
1、我们可以在接口中定义默认方法,使用default关键字,并提供默认的实现。所有实现这个接口的类都会接受默认方法的实现,除非子类提供的自己的实现。例如:
2、我们还可以在接口中定义静态方法,使用static关键字,也可以提供实现。例如:
3、接口的默认方法和静态方法的引入,其实可以认为引入了C++中抽象类的理念,以后我们再也不用在每个实现类中都写重复的代码了
三、方法引用
通常与Lambda表达式联合使用,可以直接引用已有Java类或对象的方法。一般有四种不同的方法引用:
1、构造器引用。语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数;
2、静态方法引用。语法是Class::static_method,要求接受一个Class类型的参数;
3、特定类的任意对象方法引用。它的语法是Class::method。要求方法是没有参数的;
4、特定对象的方法引用,它的语法是instance::method。要求方法接受一个参数,与3不同的地方在于,3是在列表元素上分别调用方法,而4是在某个对象上调用方法,将列表元素作为参数传入;
四、重复注解
在Java 5中使用注解有一个限制,即相同的注解在同一位置只能声明一次。Java 8引入重复注解,这样相同的注解在同一地方也可以声明多次。重复注解机制本身需要用@Repeatable注解。Java 8在编译器层做了优化,相同注解会以集合的方式保存,因此底层的原理并没有变化。
五、扩展注解的支持
Java 8扩展了注解的上下文,几乎可以为任何东西添加注解,包括局部变量、泛型类、父类与接口的实现,连方法的异常也能添加注解。
六、Optional
Java 8引入Optional类来防止空指针异常,Optional类最先是由Google的Guava项目引入的。Optional类实际上是个容器:它可以保存类型T的值,或者保存null。使用Optional类我们就不用显式进行空指针检查了。
七、Stream
Stream API是把真正的函数式编程风格引入到Java中。其实简单来说可以把Stream理解为MapRece,当然Google的MapRece的灵感也是来自函数式编程。她其实是一连串支持连续、并行聚集操作的元素。从语法上看,也很像linux的管道、或者链式编程,代码写起来简洁明了,非常酷帅!
八、Date/Time API (JSR 310)
Java 8新的Date-Time API (JSR 310)受Joda-Time的影响,提供了新的java.time包,可以用来替代 java.util.Date和java.util.Calendar。一般会用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration这些类,对于时间日期的改进还是非常不错的。
九、JavaScript引擎Nashorn
Nashorn允许在JVM上开发运行JavaScript应用,允许Java与JavaScript相互调用。
十、Base64
在Java 8中,Base64编码成为了Java类库的标准。Base64类同时还提供了对URL、MIME友好的编码器与解码器。
十一、除了这十大新特性之外,还有另外的一些新特性:
1、更好的类型推测机制:Java 8在类型推测方面有了很大的提高,这就使代码更整洁,不需要太多的强制类型转换了。
2、编译器优化:Java 8将方法的参数名加入了字节码中,这样在运行时通过反射就能获取到参数名,只需要在编译时使用-parameters参数。
3、并行(parallel)数组:支持对数组进行并行处理,主要是parallelSort()方法,它可以在多核机器上极大提高数组排序的速度。
4、并发(Concurrency):在新增Stream机制与Lambda的基础之上,加入了一些新方法来支持聚集操作。
5、Nashorn引擎jjs:基于Nashorn引擎的命令行工具。它接受一些JavaScript源代码为参数,并且执行这些源代码。
6、类依赖分析器jdeps:可以显示Java类的包级别或类级别的依赖。
7、JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)。
❸ Java8新特性有哪些
【注意】本文节选自是 DZone 指南 Java 生态系统的专题文章,作者Trisha Gee是Java资深工程师和布道者。在本文中,Trisha Gee阐述了Java 8的重要特性以及使用的原因,由OneAPM工程师翻译。
一、要点速递
1、在很多情况下,Java8 都能提升应用性能,而无需任何改变或性能调优。
2、Lambda 表达式、 Streams API 以及现有类的新方法都是提高生产力的重要工具。
3、Java8 新推出的 Optional 类型在处理 null 值时,能减少 NullPointerExceptions 的可能性,给开发者极大的灵活度。
二、其他特性:
速度更快
可以取悦老板、满足业务或运营人员的一大卖点是:Java8 运行应用时速度更快。通常,升级至 Java8 的应用都能得到速度上的提升,即便没有做任何改变或调优。对于为了迎合特定 JVM 而做出调整的应用,这或许并不适用。但 Java8 性能更优的理由还有很多:
80%以上的高端企业级应用都使用JAVA平台(电信、银行等)。JAVA是成熟的产品,已经有10年的历史。如果你想在Java行业有所建树,想要系统的进行java的学习,那么你可以来这个群,前面是二三一,中间是三一四,后面是零二八。连起来就可以了。这里有很多互联网大牛教你学习,还有免费的课程。不是想学习的就不要加了。
常见数据结构的性能提升:对广受欢迎的 HashMap 进行的基准测试表明,它们在 Java8 中的性能更好。这种提升非常吸引人——你无需学习新的 Streams API 或 Lambda 语法,甚至不需要改变现有的代码,就能提升应用的性能。
垃圾回收器提升:通常,Java 应用性能取决于垃圾回收的效率。的确,糟糕的垃圾回收会很大程度上影响应用性能。Java8 对垃圾回收做了很多改变,能有效提升性能并简化调优。最为人熟知的改变是 PermGen 的移除与 Metaspace 的引入。
Fork/Join 速度提升:fork/join 框架是在 Java7 中首次引入的,目的是简化使用 JVM 的并发程序。Java8 中投入了很多努力进一步提升该框架。现在,fork/join 在 Streams API 中用于并发操作。
此外,Java8 中还包含诸多改进以支持并发。Oracle 在 JDK 8 中总结了这些性能提升。
代码行更少
Java 经常被人们诟病其样本代码太多。为此,Java8 新的 API 采用了更具功能性的方式,专注于实现什么而不是如何实现。
Lambda 表达式
Java8 中的 Lambda 表达式不仅是 Java 已有的匿名内部类—— Java8 推出之前传递行为的方法之外的语法糖衣。Lambda 表达式采用了 Java 7 的内部改变,因此运用起来相当流畅。想了解如何使用 Lambda 表达式简化代码,请继续阅读。
集合新方法介绍
Lambda 表达式与 Streams 可能是 Java8 最大的两个卖点,较少为人知的是 Java 现在允许开发者给现有类添加新的方法,而无需为了向后兼容性折中。这样,新的方法,结合 Lambda 表达式,能在很大程序上简化代码。比如,我们常常需要判断 Map 中的某个成员是否已经存在,如果不存在则创建之。在 Java8 之前,你可能会这么做:
privatefinalMap<CustomerId,Customer>customers=newHashMap<>();
(CustomerIdcustomerId){
Customercustomer=customers.get(customerId);
if(customer==null){
customer=newCustomer(customerId);
customers.put(customerId,customer);
}
customer.incrementOrders();
}
操作“检查某个成员在 map 中是否存在,若不存在则添加之”是如此常用,Java 现在为 Map 添加了一个新方法 computeIfAbsent 来支持这个操作。该方法的第二个参数是一个 Lambda 表达式,该表达式定义了如何创建缺少的成员。
(CustomerIdcustomerId){
Customercustomer=customers.computeIfAbsent(customerId,
id->newCustomer(id));
customer.incrementOrders();
}
其实,Java8 还有一个新的特性,称为方法引用(method references),它能使我们用更简洁的代码实现该功能:
(CustomerIdcustomerId){
Customercustomer=customers.computeIfAbsent(customerId,Customer::new);
customer.incrementOrders();
}
Java8 为 Map 与 List 都添加了新方法。你可以了解一下这些新方法,看它们能节省多少行代码。
Streams API
Streams API 为查询、操纵数据提供了更多灵活度。这是一个很强大的功能。阅读这些文章能对 Streams API 有更全面的了解。在大数据时代建立流畅的数据查询会非常有趣,而且也是常用的操作。比如,你有一列书,你希望按照字母表顺序排列这些书的作者名,且不含重复。
publicList<Author>getAllAuthorsAlphabetically(List<Book>books){
List<Author>authors=newArrayList<>();
for(Bookbook:books){
Authorauthor=book.getAuthor();
if(!authors.contains(author)){
authors.add(author);
}
}
Collections.sort(authors,newComparator<Author>(){
publicintcompare(Authoro1,Authoro2){
returno1.getSurname().compareTo(o2.getSurname());
}
});
returnauthors;
}
在上面的代码中,我们首先遍历这列书,如果书的作者从未在作者列表出现,则添加之。之后,我们根据作者的姓氏按字母表顺序对这些作者排序。这种排序操作正是 Streams 擅长解决的领域:
publicList<Author>getAllAuthorsAlphabetically(List<Book>books){
returnbooks.Streams()
.map(book->book.getAuthor())
.distinct()
.sorted((o1,o2)->o1.getSurname().compareTo(o2.getSurname()))
.collect(Collectors.toList());
}
上面的做法不仅代码行更少,而且描述性更强——后来的开发者读到这段代码能够轻易理解:1、代码从书中获取作者姓名。2、只在意从未出现过的作者。3、返回的列表按照作者姓氏排序。将 Streams API 与其他新特性——方法引用(method references)、比较器(Comparator)的新方法结合使用,可以得到更加简洁的版本:
publicList<Author>getAllAuthorsAlphabetically(List<Book>books){
returnbooks.Streams()
.map(Book::getAuthor)
.distinct()
.sorted(Comparator.comparing(Author::getSurname))
.collect(Collectors.toList());
}
这里,排序方法按照作者姓氏排序,更加显而易见了。
便于并行
此前我们浅聊过更利于开箱即用的性能,除了前面提到过的特性,Java8 能更好地利用 CPU 内核。将前例中的 Streams 方法替换为 parallelStreams,JVM 会将此运算分解为不同的任务,使用 fork/join 将这些任务运行在多个核上。然而,并行化并不是加速所有运算的魔法。并行化运算总是会带来更多工作——分解运算,整合结果,因此无法总是减少时间。但是,对适合并行化的例子,这么做还是颇有效率的。
最大化减少 Null 指针
Java8 的另一个新特性是全新的 Optional 类型。该类型的含义是“我可能有值,也可能是 null。“这样一来,API 就可以区分可能为 null 的返回值与绝对不会是 null 的返回值,从而最小化 NullPointerException 异常的发生几率。
Optional 最赞的用处是处理 null。例如,假设我们要从一个列表中找一本特定的书,新创建的 findFirst() 方法会返回 Optional 类型的值,表明它无法确保是否找到特定的值。有了这个可选择的值,我们接下来可以决定,如果是 null 值要如何处理。如果想要抛出一个自定义的异常,我们可以使用 orElseThrow:
publicBookfindBookByTitle(List<Book>books,Stringtitle){
Optional<Book>foundBook=books.Streams()
.filter(book->book.getTitle().equals(title))
.findFirst();
returnfoundBook.orElseThrow(()->newBookNotFoundException("Didnotfindbookwithtitle"+title));
}
或者,你可以返回其他书:
returnfoundBook.orElseGet(()->getRecommendedAlternativeBook(title));
或者,返回 Optional 类型,这样,该方法的调用者可以自己决定书没找到时要怎么做。
总结:Java8 作为 Java 语言的一次重大发布,包含语法上的更改、新的方法与数据类型,以及一些能默默提升应用性能的隐性改善。Oracle 已经不再支持 Java 7,因此许多公司都被迫向 Java8 转移。好消息是,Java8 对业务、现有的应用以及期望提高生产力的开发者都好好多。
❹ java中的空指针异常怎么解决
原文:https://www.hu.com/question
你这个问题的解决
问题定位:
在堆栈异常信息的第一行就可以定位到是哪里出了空指针,倘若这里不是你写的类,可以往下翻一下,找到你写的类,就是这里出现的空指针。
问题解决:
对一个空对象调用里面的方法或者属性的时候会报空指针,检查这个对象为什么是空即可。
Java 空指针异常的若干解决方案
Java 中任何对象都有可能为空,当我们调用空对象的方法时就会抛出 NullPointerException 空指针异常,这是一种非常常见的错误类型。我们可以使用若干种方法来避免产生这类异常,使得我们的代码更为健壮。本文将列举这些解决方案,包括传统的空值检测、编程规范、以及使用现代 Java 语言引入的各类工具来作为辅助。
运行时检测
最显而易见的方法就是使用 if (obj == null) 来对所有需要用到的对象来进行检测,包括函数参数、返回值、以及类实例的成员变量。当你检测到 null 值时,可以选择抛出更具针对性的异常类型,如 IllegalArgumentException,并添加消息内容。我们可以使用一些库函数来简化代码,如 Java 7 开始提供的 Objects#requireNonNull 方法:
public void testObjects(Object arg) {
Object checked = Objects.requireNonNull(arg, "arg must not be null");
checked.toString();}
Guava 的 Preconditions 类中也提供了一系列用于检测参数合法性的工具函数,其中就包含空值检测:
public void testGuava(Object arg) {
Object checked = Preconditions.checkNotNull(arg, "%s must not be null", "arg");
checked.toString();
}
我们还可以使用 Lombok 来生成空值检测代码,并抛出带有提示信息的空指针异常:
public void testLombok(@NonNull Object arg) {
arg.toString();
生成的代码如下:
public void testLombokGenerated(Object arg) {
if (arg == null) {
throw new NullPointerException("arg is marked @NonNull but is null");
}
arg.toString();
}
这个注解还可以用在类实例的成员变量上,所有的赋值操作会自动进行空值检测。
编程规范
·通过遵守某些编程规范,也可以从一定程度上减少空指针异常的发生。
使用那些已经对 null 值做过判断的方法,如 String#equals、String#valueOf、以及三方库中用来判断字符串和集合是否为空的函数:
if (str != null && str.equals("text")) {}
if ("text".equals(str)) {}
if (obj != null) { obj.toString(); }
String.valueOf(obj); // "null"
// from spring-core
StringUtils.isEmpty(str);
CollectionUtils.isEmpty(col);
// from guava
Strings.isNullOrEmpty(str);
// from commons-collections4
CollectionUtils.isEmpty(col);
·如果函数的某个参数可以接收 null 值,考虑改写成两个函数,使用不同的函数签名,这样就可以强制要求每个参数都不为空了:
public void methodA(Object arg1) {
methodB(arg1, new Object[0]);
}
public void methodB(Object arg1, Object[] arg2) {
for (Object obj : arg2) {} // no null check
}
·如果函数的返回值是集合类型,当结果为空时,不要返回 null 值,而是返回一个空的集合;如果返回值类型是对象,则可以选择抛出异常。Spring JdbcTemplate 正是使用了这种处理方式:
// 当查询结果为空时,返回 new ArrayList<>()
jdbcTemplate.queryForList("SELECT * FROM person");
// 若找不到该条记录,则抛出
jdbcTemplate.queryForObject("SELECT age FROM person WHERE id = 1", Integer.class);
// 支持泛型集合
public <T> List<T> testReturnCollection() {
return Collections.emptyList();
}
静态代码分析
Java 语言有许多静态代码分析工具,如 Eclipse IDE、SpotBugs、Checker Framework 等,它们可以帮助程序员检测出编译期的错误。结合 @Nullable 和 @Nonnull 等注解,我们就可以在程序运行之前发现可能抛出空指针异常的代码。
但是,空值检测注解还没有得到标准化。虽然 2006 年 9 月社区提出了 JSR 305 规范,但它长期处于搁置状态。很多第三方库提供了类似的注解,且得到了不同工具的支持,其中使用较多的有:
javax.annotation.Nonnull:由 JSR 305 提出,其参考实现为 com.google.code.findbugs.jsr305;
org.eclipse.jdt.annotation.NonNull:Eclipse IDE 原生支持的空值检测注解;
e.umd.cs.findbugs.annotations.NonNull:SpotBugs 使用的注解,基于 findbugs.jsr305;
org.springframework.lang.NonNull:Spring Framework 5.0 开始提供;
org.checkerframework.checker.nullness.qual.NonNull:Checker Framework 使用;
android.support.annotation.NonNull:集成在安卓开发工具中;
我建议使用一种跨 IDE 的解决方案,如 SpotBugs 或 Checker Framework,它们都能和 Maven 结合得很好。
SpotBugs 与 @NonNull、@CheckForNull
SpotBugs 是 FindBugs 的后继者。通过在方法的参数和返回值上添加 @NonNull 和 @CheckForNull 注解,SpotBugs 可以帮助我们进行编译期的空值检测。需要注意的是,SpotBugs 不支持 @Nullable 注解,必须用 @CheckForNull 代替。如官方文档中所说,仅当需要覆盖 @ParametersAreNonnullByDefault 时才会用到 @Nullable。
官方文档 中说明了如何将 SpotBugs 应用到 Maven 和 Eclipse 中去。我们还需要将 spotbugs-annotations 加入到项目依赖中,以便使用对应的注解。
以下是对不同使用场景的说明:
对于 Eclipse 用户,还可以使用 IDE 内置的空值检测工具,只需将默认的注解 org.eclipse.jdt.annotation.Nullable 替换为 SpotBugs 的注解即可:
Checker Framework 与 @NonNull、@Nullable
Checker Framework 能够作为 javac 编译器的插件运行,对代码中的数据类型进行检测,预防各类问题。我们可以参照 官方文档,将 Checker Framework 与 maven-compiler-plugin 结合,之后每次执行 mvn compile 时就会进行检查。Checker Framework 的空值检测程序支持几乎所有的注解,包括 JSR 305、Eclipse、甚至 lombok.NonNull。
Checker Framework 默认会将 @NonNull 应用到所有的函数参数和返回值上,因此,即使不添加这个注解,以下程序也是无法编译通过的:
Checker Framework 对使用 Spring Framework 5.0 以上的用户非常有用,因为 Spring 提供了内置的空值检测注解,且能够被 Checker Framework 支持。一方面我们无需再引入额外的 Jar 包,更重要的是 Spring Framework 代码本身就使用了这些注解,这样我们在调用它的 API 时就能有效地处理空值了。举例来说,StringUtils 类里可以传入空值的函数、以及会返回空值的函数都添加了 @Nullable 注解,而未添加的方法则继承了整个框架的 @NonNull 注解,因此,下列代码中的空指针异常就可以被 Checker Framework 检测到了:
Optional 类型
Java 8 引入了 Optional<T> 类型,我们可以用它来对函数的返回值进行包装。这种方式的优点是可以明确定义该方法是有可能返回空值的,因此调用方必须做好相应处理,这样也就不会引发空指针异常。但是,也不可避免地需要编写更多代码,而且会产生很多垃圾对象,增加 GC 的压力,因此在使用时需要酌情考虑。
方法的链式调用很容易引发空指针异常,但如果返回值都用 Optional 包装起来,就可以用 flatMap 方法来实现安全的链式调用了:
Java 8 Stream API 同样使用了 Optional 作为返回类型:
此外,Java 8 还针对基础类型提供了单独的 Optional 类,如 OptionalInt、OptionalDouble 等,在性能要求比较高的场景下很适用。
其它 JVM 语言中的空指针异常
Scala 语言中的 Option 类可以对标 Java 8 的 Optional。它有两个子类型,Some 表示有值,None 表示空。
除了使用 Option#isEmpty 判断,还可以使用 Scala 的模式匹配:
Scala 的集合处理函数库非常强大,Option 则可直接作为集合进行操作,如 filer、map、以及列表解析(for-comprehension):
Kotlin 使用了另一种方式,用户在定义变量时就需要明确区分 可空和不可空类型。当可空类型被使用时,就必须进行空值检测。
Kotlin 的特性之一是与 Java 的可互操作性,但 Kotlin 编译器无法知晓 Java 类型是否为空,这就需要在 Java 代码中使用注解了,而 Kotlin 支持的 注解 也非常广泛。Spring Framework 5.0 起原生支持 Kotlin,其空值检测也是通过注解进行的,使得 Kotlin 可以安全地调用 Spring Framework 的所有 API。
结论
在以上这些方案中,我比较推荐使用注解来预防空指针异常,因为这种方式十分有效,对代码的侵入性也较小。所有的公共 API 都应该使用 @Nullable 和 @NonNull 进行注解,这样就能强制调用方对空指针异常进行预防,让我们的程序更为健壮。