Java面试基础之String、Integer、Object
String
1、String是Java基本数据类型吗?可以被继承吗?
String不是java的基本数据类型,是引用数据类型,(八大基本数据类型自己内心背一下)
String属于类,引用数据类型为;类。数组,接口。
String不可以被继承!因为String类被final所修饰(自己想一下final的用法)
2、String和StringBuilder、StringBuffer的区别?
推荐阅读https://javabetter.cn/string/builder-buffer.html#stringbuffer%E5%92%8Cstringbuilder%E7%9A%84%E5%8C%BA%E5%88%AB
String、StringBuilder、StringBuffer在Java中都是处理字符串的,他们之间的区别就是String不可以变,StringBuilder和StringBuffer是可以变得。StringBuilder和StringBuffer类似都有append等方法,但是StringBuffer在每个方法上都加上了syschronized关键字,所以StringBuffer是线程安全的。
String:类的对象是不可以改变的,一旦被创立,她所包含的字符内容是不可以改变的。每次对String进行的操作,实际上都会生成一个新的String对象。而不是修改原有对象。这有可能导致性能过载,尤其在大量字符的操作之下。
StringBuilder:其中提供了一系列的方法来进行字符串的增删改查的操作,这些操作是在原有的的字符串对象的底层数组之上进行,不是生成新的String对象。它不是线程安全的(没有外部同步的情况之下,不适用于多线程的环境)。相比较在String,在频繁的进行对字符串进行操作时,StringBuilder可以提供更好的性能。(Java中字符串的“+”操作就是StringBuilder来实现的)
StringBuffer:相比较StringBuilder,他在每个方法前都加了一个synchronized关键字加锁,所以是线程安全的
使用场景的总结:
String:适用于字符串不经常改变的。使用字符串常量或少量字符串操作时使用
StringBuilder:适用于单线程环境下需要频繁修改字符串内容的场景,比如:在循环中拼接和修改字符串。
StringBuffer:适用于多线程环境下需要频繁修改字符串内容的场景,保证了字符串的操作的线程安全。
3、String str1 = new String(“abc”)和String str2 = “abc” 的区别?
两个语句都会在字符串的常量池中检查是否已经存在“abc”,如果有就直接引用,,反之,如果没有,就会在常量池中创建“abc”对象,但是不同的是,String str1 = new String(“abc”)还会通过 new String()在堆里创建一个对象(后者可以理解为被前者包含)
String s = new String(“abc”)创建了几个对象?
一个或者两个! 如果字符串池中有abc的话就是一个,反之就是2个。
如果没有abc的话,此时会创建以下两个对象:
①:一个是字符串常量池中的实例:abc
②:另一个是通过new 得到的String的对象的实例,在堆中。
4、String是不可变类吗?字符串拼接是如何实现的?’
String是不可变得,这意味着一旦一个String对象被创建,其存储得文本内容就不会改变,原因如下:
①:不可变性使得String对象在使用中更加安全,因为字符串通常在java中要进行网络连接,打开文件等操作
②:不可变得对象因为状态不会改变,所以更容易进行缓存和重用,字符串常量池正是基于这个原因。
当代码中出现字符串字面量时,JVM会确保所有得引用都指向常量池中得同一个对象,从而节约内存。
③:因为String的内容不可以变,所以它的哈希值也就会固定不变,这使得String对象特别适合作为HashMap和HashSet等集合的键,因为计算哈希值只需要进行一次,提高哈希表的操作的效率。
因为String是不可变的,所以两个字符串对象相加拼接,会生成一个新的对象。
JDK8之后,对+进行了优化,会基于SringBuilder的append方法进行拼接。
String a = "hello ";
String b = "world!";
StringBuilder sb = new StringBuilder();
sb.append(a);
sb.append(b);
String ab = sb.toString();
因此,如果笼统地讲,通过加号拼接字符串时会创建多个 String 对象是不准确的。因为加号拼接在编译期还会创建一个 StringBuilder 对象,最终调用 toString()
方法的时候再返回一个新的 String 对象。
5、intern方法有什么作用?
-
如果当前字符串内容存在于字符串常量池(即 equals()方法为 true,也就是内容一样),直接返回字符串常量池中的字符串
-
否则,将此 String 对象添加到池中,并返回 String 对象的引用
-
(比较鸡肋,没什么屌用,了解即可)
Integer
1、Integer a= 127,Integer b = 127;Integer c= 128,Integer d = 128;相等吗?
在Jvaa自动装箱的过程中,会使用valueOf()方法来创建Integer对象。
Integer.valueOf()方法会针对数值在-128到127之间的Integer对象使用缓存,因此a和b实际上是引用了常量池中相同的Integer对象。
因为128 超出了Integer缓存的对象(-128到127),因此在自动装箱过程中创建两个不同的Integer对象,他们有不同的的地址值。
所以结果就是:a=b,c != (不等)d
要比较Integer对象的数值是否相等时,应该使用equals方法,而不是==
使用equals方法时,a和b、c和d的比较结构都为true,因为equals()比较的是数值,而不是地址值。
new Integer(10) == new Integer(10) 相等吗
在 Java 中,使用new Integer(10) == new Integer(10)
进行比较时,结果是 false。
这是因为 new 关键字会在堆(Heap)上为每个 Integer 对象分配新的内存空间,所以这里创建了两个不同的 Integer 对象,它们有不同的内存地址。
当使用==运算符比较这两个对象时,实际上比较的是它们的内存地址(地址值),而不是它们的值,因此即使两个对象代表相同的数值(10),结果也是 false。
2、String怎么转成Integer的?原理
两种方法:Integer.parseInt(String s) (转成int类型) 和 Integer.valueOf(String s) (转成Integer类型)
一种有参构造函数: public Integer(String s){this.value = parseInt(s, 10) }
不关哪一种,调用的都是Integer类中的parseInt(String s, int radix)方法
Object
1、Object类的常见方法?
万物皆对象
万物指的是Java中所有的类,而这些类都是Object的子类
Object大致提供了11种方法,大致可分为六类:
对象比较:
①:public native int hashCode(): 用于返回对象的哈希码。
②:public boolean equals(Object obj)
:用于比较 2 个对象的内存地址是否相等。
③:protected native Object clone() throws CloneNotSupportedException
:naitive 方法,返回此对象的一个副本。默认实现只做浅拷贝open in new window,且类必须实现 Cloneable 接口。(Object 本身没有实现 Cloneable 接口,所以在不重写 clone 方法的情况下直接直接调用该方法会发生 CloneNotSupportedException 异常。)
④:toString()方法 返回对象的字符串表示。一般会重写toString方法。 例如Lombok小辣椒 @Data注解会重写toString方法
⑤:lock.wait()方法 ,线程进入等待
⑥、public final native void wait(long timeout) throws InterruptedException
:等待 timeout 毫秒,如果在 timeout 毫秒内没有被唤醒,会自动唤醒。
⑦、public final void wait(long timeout, int nanos) throws InterruptedException
:更加精确了,等待 timeout 毫秒和 nanos 纳秒,如果在 timeout 毫秒和 nanos 纳秒内没有被唤醒,会自动唤醒。
⑧:lock.notify()随机唤醒一个等待的线程
⑨:nitifyAll() 唤醒所有在等待的线程
⑩:getClass() 反射,获取对象的信息,比如说类名
public static void main(String[] args) {
User user = new User();
Class<? extends User> aClass = user.getClass();
System.out.println(aClass);
}
比如此代码:打印出来aClass为 class com .author.model.User(类)
底层源码:重写了toString
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
一个简单的三目运算。
11、finalize 当垃圾回收器决定回收对象占用的内存时调用此方法。用于清理资源,但 Java 不推荐使用,因为它不可预测且容易导致问题,Java 9 开始已被弃用。
) ? “” : "class "))
+ getName();
}
一个简单的三目运算。
11、finalize 当垃圾回收器决定回收对象占用的内存时调用此方法。用于清理资源,但 Java 不推荐使用,因为它不可预测且容易导致问题,Java 9 开始已被弃用。