jdk8运行jdk7的代码
Java 7,TreeSet和NullPointerException。
最近,我尝试用Java 7编译一个用Java 6开发的项目。在执行测试过程中发生了很多有趣的事情,在Java 6中使用Java 7平稳运行的测试失败了! 因此,我必须理解为什么,这就是我发现的内容……首先要了解的上下文:在该项目中,我或多或少有一个简单的Hibernate Entity,如下所示。
package com.marco.test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.hibernate.validator.NotNull;
@Entity
@Table(...)
public class ABean {...private String name;@Column(name = "name", nullable = false)@NotNullpublic String getName() {return name;}public void setName(String name) {this.name = name;}
}
请注意,字段“名称”为nullable = false并标有@NotNull 。 这是为了告诉Hibernate在用户尝试创建或将此列更新为Null的情况下使验证失败。 我也有该实体的比较器。 该比较器使用名称字段来比较Entity(这只是我在项目中的简化版本,当然,我不基于字符串长度订购Bean)
package com.marco.test;
import java.util.Comparator;
public class ABeanComparator implements Comparator<ABean> {@Overridepublic int compare(ABean o1, ABean o2) {if (o1.getName().length() > o2.getName().length()) {return 1;} else if (o1.getName().length() < o2.getName().length()) {return -1;} else {return 0;}}
}
请注意,字段名称没有空检查,在我的项目中,Hibernate已经在处理它。 现在,我有一个测试,该测试创建一个空的Entity并将其存储到TreeSet中,然后执行其他我们在这里并不真正关心的东西。 测试的开始类似于以下代码:
package com.marco.test;
import java.util.SortedSet;
import java.util.TreeSet;
public class SortedTestTest {public static void main(String[] args) {ABean aBean = new ABean();SortedSet<ABean> sortedSet = new TreeSet<ABean>(new ABeanComparator());sortedSet.add(aBean);}
}
如果我使用Java 6运行此程序,一切正常。 但是,对于Java 7,我有一个NullPointerException。
Exception in thread "main" java.lang.NullPointerExceptionat com.marco.test.ABeanComparator.compare(ABeanComparator.java:9)at com.marco.test.ABeanComparator.compare(ABeanComparator.java:1)at java.util.TreeMap.compare(TreeMap.java:1188)at java.util.TreeMap.put(TreeMap.java:531)at java.util.TreeSet.add(TreeSet.java:255)at com.marco.test.SortedTestTest.main(SortedTestTest.java:14)
为什么? 这就是为什么:
public V put(K key, V value) {Entry<K,V> t = root;if (t == null) {compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}
在Java 7中,当第一个Object添加到TreeSet时 (如果(t == null)),将执行与自身的比较(compare(key,key))。 然后,compare方法将调用比较器(如果有的话),并且name属性将具有NullPointerException。
// Little utilities/*** Compares two keys using the correct comparison method for this TreeMap.*/final int compare(Object k1, Object k2) {return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2): comparator.compare((K)k1, (K)k2);}
提出的问题多于答案:
- 如果您知道TreeSet中的对象是第一个也是唯一的,为什么还要进行比较?
- 我的猜测是他们想做的是运行一个简单的Null检查。
- 为什么不创建适当的null检查方法?
- 没有答案
- 为什么浪费CPU和内存运行不需要的比较?
- 没有答案
- 为什么将一个对象与其自身进行比较(compare(key,key))?
- 没有答案
这是Java 6中TreeSet的put方法,可以看到比较被注释掉了。
public V put(K key, V value) {Entry<K, V> t = root;if (t == null) {// TBD:// 5045147: (coll) Adding null to an empty TreeSet should// throw NullPointerException//// compare(key, key); // type checkroot = new Entry<K, V>(key, value, null);size = 1;modCount++;return null;}
您看到评论了吗? 向空的TreeSet添加null会引发NullPointerException。 因此,只需检查key是否为null,就不要进行无用的比较! 结论? 始终尝试分析您使用的代码,因为即使在jdk中,也存在错误代码!
翻译自: https://www.javacodegeeks.com/2013/04/even-in-the-jdk-there-is-bad-code.html
jdk8运行jdk7的代码