标签:整数 数据 答案 long stringbu search 可重复 才有 对象类型
文章以及源代码已被收录到:https://github.com/mio4/Java-Gold
Java中的数据类型分为基本数据类型和引用数据类型:
byte
、short
、int
、long
float
、double
char
boolean
==
比较的是它们的值==
比较的是它们在内存中存放的地址(堆内存地址)举例说明:
public static void main(String[] args) {
//基本数据类型
int num1 = 100;
int num2 = 100;
System.out.println("num1 == num2 : " + (num1 == num2) + "\n");
//引用类型,其中‘System.identityHashCode‘可以理解为打印对象地址
String str1 = "mio4";
String str2 = "mio4";
System.out.println("str1 address : " + System.identityHashCode(str1));
System.out.println("str2 address : " + System.identityHashCode(str1));
System.out.println("str1 == str2 : " + (str1 == str2) + "\n");
String str3 = new String("mio4");
String str4 = new String("mio4");
System.out.println("str3 address : " + System.identityHashCode(str3));
System.out.println("str4 address : " + System.identityHashCode(str4));
System.out.println("str3 == str4 : " + (str3 == str4));
}
运行上面的代码,可以得到以下结果:
num1 == num2 : true
str1 address : 1639705018
str2 address : 1639705018
str1 == str2 : true
str3 address : 1627674070
str4 address : 1360875712
str3 == str4 : false
可以看到str1和str2的内存地址都是1639705018
,所以使用==
判断为true
,
但是str3和str4的地址是不同的,所以判断为false
。
在Java语言中,所有类都是继承于Object
这个超类的,在这个类中也有一个equals()
方法,那么我们先来看一下这个方法。
可以看得出,这个方法很简单,就是比较对象的内存地址的。所以在对象没有重写这个方法时,默认使用此方法,即比较对象的内存地址值。但是类似于String、Integer等类均已重写了equals()
。下面以String
为例。
很明显,String的equals()方法仅仅是对比它的 数据值,而不是对象的 内存地址 。
以 String
为例测试一下:
public static void main(String[] args) {
String str1 = "mio4";
String str2 = "mio4";
String str3 = new String("mio4");
String str4 = new String("mio4");
System.out.println("str1 address : " + System.identityHashCode(str1));
System.out.println("str2 address : " + System.identityHashCode(str1));
System.out.println("str1.equals(str2) : " + str1.equals(str2) + "\n");
System.out.println("str3 address : " + System.identityHashCode(str3));
System.out.println("str4 address : " + System.identityHashCode(str4));
System.out.println("str3.equals(str4) : " + str3.equals(str4) + "\n");
}
测试输出为如下,可以看出str3
和str4
地址不同,但是因为String字符串内容相同,所以equals判断为true
str1 address : 1639705018
str2 address : 1639705018
str1.equals(str2) : true
str3 address : 1627674070
str4 address : 1360875712
str3.equals(str4) : true
Java中的集合(Collection)有三类,一类是List,一类是Queue,集合内的元素是有序的,元素可以重复;再有一类就是Set,一个集合内的元素无序,但元素不可重复。
前提: 谈到hashCode就不得不说equals方法,二者均是Object类里的方法。由于Object类是所有类的基类,所以一切类里都可以重写这两个方法。
总结来说,需要注意的是:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {}
核心解释:
? 1.为了实现字符串池
? 2.为了线程安全
? 3.为了实现String可以创建HashCode不可变性
String
类型的初始化在Java中分为两类:
new
像一个普通的对象那样初始化一个String
实例。前者在常量池l中开辟一个常量,并返回相应的引用,而后者是在堆中开辟一个常量,再返回相应的对象。所以,两者的reference肯定是不同的:
public static void main(String... args) {
String s1 = "abcd";
String s2 = new String("abcd");
System.out.println(s1 == s2); // false
}
而常量池中的常量是可以被共享用于节省内存开销和创建时间的开销(这也是引入常量池的原因),例如:
public static void main(String... args) {
String s1 = "abcd";
String s2 = "abcd";
System.out.println(s1 == s2); // true
}
结合这两者,其实还可以回答另外一个常见的面试题目:
public static void main(String... args) {
String s = new String("abcd");
}
这句话创建了几个对象?
首先毫无疑问,"abcd"
本身是一个对象,被放于常量池。而由于这里使用了new
关键字,所以s
得到的对象必然是被创建在heap里的。所以,这里其实一共创建了2个对象。
需要注意的是,如果在这个函数被调用前的别的地方,已经有了"abcd"
这个字符串,那么它就事先在常量池中被创建了出来。此时,这里就只会创建一个对象,即创建在heap的new String("abcd")
对象。
String是不可变类,一旦创建了String对象,我们就无法改变它的值。因此,它是线程安全的,可以安全地用于多线程环境中。
因为字符串是不可变的,当创建字符串时,它的它的hashcode被缓存下来,不需要再次计算。因为HashMap内部实现是通过key的hashcode来确定value的存储位置,所以相比于其他对象更快。这也是为什么我们平时都使用String作为HashMap对象。
String.intern()
方法,可以在runtime期间将常量加入到常量池(constant pool)。它的运作方式是:
intern()
方法返回这个存在于constant pool中的常量的引用。intern()
方法返回这个新创建的常量的引用。示例:
public static void main(String... args) {
String s1 = "abcd";
String s2 = new String("abcd");
/**
* s2.intern() will first search String constant pool,
* of which the value is the same as s2.
*/
String s3 = s2.intern();
// As s1 comes from constant pool, and s3 is also comes from constant pool, they‘re same.
System.out.println(s1 == s3);
// As s2 comes from heap but s3 comes from constant pool, they‘re different.
System.out.println(s2 == s3);
}
/**
* Output:
* true
* false
*/
回顾到最开始的第一部分,为什么要引入intern()
这个函数呢?就是因为,虽然"abcd"
是被分配在常量池里的,但是,一旦使用new String("abcd")
就会在heap中新创建一个值为abcd
的对象出来。试想,如果有100个这样的语句,岂不是就要在heap里创建100个同样值的对象?!这就造成了运行的低效和空间的浪费。
于是,如果引入了intern()
它就会直接去常量池找寻是否有值相同的String对象,这就极大地节省了空间也提高了运行效率。
String s1 = "ab";
String s2 = "abc";
String s3 = s1 + "c";
System.out.println(s3 == s2); //false 不相等,s1是变量,编译的时候确定不了值,在内存中会创建值,s3在堆内存中,。s2在常量池,所以不相等。
System.out.println(s3.equals(s2)); //true 比较两个对象的值相等。
关于上述代码的解释:
String s1 = "abc";
String s2 = "abc";
s1会在常量池中创建,s2先查看常量池中有没有,如果有的话就指向它,如果没有就在常量池中创建一个然后指向它。所以s1和s2的两种比较是相同的。
String s1 = new String("Hello");
String s2 = new String("Hello");
答案是3个对象.
第一,行1 字符串池中的“hello”对象。
第二,行1,在堆内存中带有值“hello”的新字符串。
第三,行2,在堆内存中带有“hello”的新字符串。这里“hello”字符串池中的字符串被重用。
synchronized
修饰:
https://blog.csdn.net/justloveyou_/article/details/52464440
https://www.jianshu.com/p/875a3d2b5690
https://www.jianshu.com/p/9c7f5daac283
Java面试炼金系列 (1) | 关于String类的常见面试题剖析
标签:整数 数据 答案 long stringbu search 可重复 才有 对象类型
原文地址:https://www.cnblogs.com/Hooooober/p/13661843.html