Java泛型和判断对象相等(四)
1.Java泛型了解吗?什么是类型擦除?介绍一下常用的通配符?
Java泛型是jdk5引入的新特性,泛型提供了编译时类型安全检测机制。当我们定义一个list集合是Integer类型的,我们添加String类型会自动报错。
Java泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,类型擦除看这个文章
List<Integer> list = new ArrayList<>();
list.add(12);
//这里直接添加会报错
list.add("a");
Class<? extends List> clazz = list.getClass();
Method add = clazz.getDeclaredMethod("add", Object.class);
//但是通过反射添加,是可以的
add.invoke(list, "kl");
System.out.println(list)
常用的通配符为: T,E,K,V,?
? 表示不确定的 java 类型
T (type) 表示具体的一个java类型
K V (key value) 分别代表java键值中的Key Value
E (element) 代表Element
2.Java中创建的对象存放在jvm哪里
- 基本类型的变量和对象的引用都是放在栈里面
- 对象本身放在堆里面
Person person = new Person();
Person 存放在元空间,也可以说是方法区
person 存放在Java栈的局部变量表中
new Person() 存放在Java堆中
3.显式的String常量放在常量池
String a = "violet";
String b = "violet";
System.out.println(a==b); //true
System.out.println(a.equals(b)); //true
- 第一句代码执行后就在常量池中创建了一个值为violet的String对象;
- 第二句执行时,因为常量池中存在violet所以就不再创建新的String对象了。
- 此时该字符串的引用在虚拟机栈里面。
4.String对象放在堆中
而堆区存对象。==是比较地址,equals()比较对象内容。
String c= new String("violet");
String d = new String("violet");
System.out.println(c==d); //false
System.out.println(c.equals(d)); //true
- Class被加载时就在常量池中创建了一个值为violet的String对象,第一句执行时会在堆里创建new String(“violet”)对象;
- 第二句执行时,因为常量池中存在violet所以就不再创建新的String对象了,直接在堆里创建new String(“violet”)对象。
String s = new String(“xyz”);产生几个对象?一个或两个,如果常量池中原来没有”xyz”,就是两个。
5. ==与equals()
- == 它的作用是判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象。(基本数据类型== 比较的是值,引用数据类型== 比较的是内存地址)
- equals()比较的是值
6. hashCode()与 equals()
两个对象的hashCode相等,但是它们==不相等
String c = new String("violet1");
String d = new String("violet1");
System.out.println(c.hashCode()+" "+d.hashCode()); //463141778 463141778
System.out.println(c.hashCode()==d.hashCode()); //true
hashCode()介绍
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个 int 整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在 JDK 的 Object 类中,这就意味着 Java 中的任何类都包含有 hashCode() 函数。另外需要注意的是: Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法通常用来将对象的 内存地址 转换为整数之后返回。
public native int hashCode();
为什么重写 equals 时必须重写 hashCode 方法?
如果两个对象相等,则 hashcode 一定也是相同的。两个对象相等,对两个对象分别调用 equals 方法都返回 true。但是,两个对象有相同的 hashcode 值,它们也不一定是相等的 。因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。
- hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
为什么两个对象有相同的 hashcode 值,它们也不一定是相等的?
因为 hashCode() 所使用的杂凑算法也许刚好会让多个对象传回相同的杂凑值。越糟糕的杂凑算法越容易碰撞,但这也与数据值域分布的特性有关(所谓碰撞也就是指的是不同的对象得到相同的 hashCode。