Java基础面试题

Java最全面试题->Java基础面试题->JavaSE面试题->基础语法面试题 隐式转换:自动转换类型,大范围的变量能够接受小范围的数据显示转换:强制类型转换,大范围的数据强制复制给小类型的数据拆箱:把包装类转换成基本数据类型装箱:把基本数据类型转换成包装类jdk5的新特性,定义类和接口的候使用类型参数,主要运用在集合上。 阅读详情

Java基础 面试题

1. 解释下什么是面向对象?面向对象和面向过程的区别?

面向对象是一种基于面向过程的编程思想,是向现实世界模型的自然延伸,这是一种“万物皆对象”的编程思想。由执行者变为指挥者,在现实生活中的任何物体都可以归为一类事物,而每一个个体都是一类事物的实例。面向对象的编程是以对象为中心,以消息为驱动。
区别: (1)编程思路不同:面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。
(2)封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。
(3)面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势很明显

2. 面向对象的三大特性?分别解释下?

(1)封装:通常认为封装是把数据和操作数据的方法封装起来,对数据的访问只能通过已定义的接口。
(2)继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类/基类),得到继承信息的被称为子类(派生类)。
(3)多态:分为编译时多态(方法重载)和运行时多态(方法重写)。要实现多态需要做两件事:一是子类继承父类并重写父类中的方法,二是用父类型引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为。
几点补充
1)子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。因为在一个子类被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类的对象;
(2)子类可以拥有自己属性和方法; (3)子类可以用自己的方式实现父类的方法。(重写)

3. JDK、JRE、JVM 三者之间的关系?

JDK(Java Development Kit):是 Java 开发工具包,是整个 Java 的核心,包括了 Java 运行环境
JRE、Java 工具和 Java 基础类库。 JRE( Java Runtime Environment):是 Java 的运行环境,包含
JVM 标准实现及 Java 核心类库。 JVM(Java Virtual Machine):是 Java 虚拟机,是整个 Java实现跨平台的最核心的部分,能够运行以 Java 语言写作的软件程序。所有的 Java 程序会首先被编译为 .class的类文件,这种类文件可以在虚拟机上执行。

4. 重载和重写的区别?

(1)重载:编译时多态、同一个类中同名的方法具有不同的参数列表、不能根据返回类型进行区分【因为:函数调用时不能指定类型信息,编译器不知道你要调哪个函数】;
(2)重写(又名覆盖):运行时多态、子类与父类之间、子类重写父类的方法具有相同的返回类型、更好的访问权限。

5. Java 中是否可以重写一个 private 或者 static 方法?

Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编译时静态绑定的。static
方法跟类的任何实例都不相关,所以概念上不适用。 Java 中也不可以覆盖 private 的方法,因为 private
修饰的变量和方法只能在当前类中使用, 如果是其他的类继承当前类是不能访问到 private 变量或方法的,当然也不能覆盖。

静态方法补充:静态的方法可以被继承,但是不能重写。如果父类和子类中存在同样名称和参数的静态方法,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。通俗的讲就是父类的方法和子类的方法是两个没有关系的方法,具体调用哪一个方法是看是哪个对象的引用;这种父子类方法也不在存在多态的性质。

6. 构造方法有哪些特性?

(1)名字与类名相同;
(2)没有返回值,但不能用 void 声明构造函数;
(3)成类的对象时自动执行,无需调用。

7. 在 Java 中定义一个不做事且没有参数的构造方法有什么作用?

因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类中特定的构造方法,则编译时将发生错误,因为
Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是:在父类里加上一个不做事且没有参数的构造方法。

8. Java 中创建对象的几种方式?

1、使用 new 关键字;
2、使用 Class 类的 newInstance方法,该方法调用无参的构造器创建对象(反射):Class.forName.newInstance();
3、使用 clone() 方法;
4、反序列化,比如调用 ObjectInputStream 类的 readObject() 方法。

9. 抽象类和接口有什么区别?

(1)抽象类中可以定义构造函数,接口不能定义构造函数;
(2)抽象类中可以有抽象方法和具体方法,而接口中只能有抽象方法(public
abstract);
(3)抽象类中的成员权限可以是 public、默认、protected(抽象类中抽象方法就是为了重写,所以不能被private 修饰),而接口中的成员只可以是 public(方法默认:public abstrat、成员变量默认:publicstatic final);
(4)抽象类中可以包含静态方法,而接口中不可以包含静态方法;
JDK 8 中的改变:
1、在JDK1.8中,允许在接口中包含带有具体实现的方法,使用 default 修饰,这类方法就是默认方法。
2、抽象类中可以包含静态方法,在JDK1.8 之前接口中不能包含静态方法,JDK1.8以后可以包含。之前不能包含是因为,接口不可以实现方法,只可以定义方法,所以不能使用静态方法(因为静态方法必须实现)。现在可以包含了,只能直接用接口调用静态方法。JDK1.8仍然不可以包含静态代码块。

10. 静态变量和实例变量的区别?

静态变量:是被 static
修饰的变量,也称为类变量,它属于类,因此不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;静态变量可以实现让多个对象共享内存。
实例变量:属于某一实例,需要先创建对象,然后通过对象才能访问到它。

11. short s1 = 1;s1 = s1 + 1;有什么错?那么 short s1 = 1; s1 += 1;呢?有没有错误?

对于 short s1 = 1; s1 = s1 + 1; 来说,在 s1 + 1 运算时会自动提升表达式的类型为 int ,那么将 int
型值赋值给 short 型变量,s1 会出现类型转换错误。 对于 short s1 = 1; s1 += 1; 来说,+= 是 Java
语言规定的运算符,Java 编译器会对它进行特殊处理,因此可以正确编译。

12. Integer 和 int 的区别?

(1)int 是 Java 的八种基本数据类型之一,而 Integer 是 Java 为 int 类型提供的封装类;
(2)int型变量的默认值是 0,Integer 变量的默认值是 null,这一点说明 Integer 可以区分出未赋值和值为 0 的区分;
(3)Integer 变量必须实例化后才可以使用,而 int 不需要。
Integer 和 int 的比较延伸:
1、由于 Integer变量实际上是对一个 Integer 对象的引用,所以两个通过 new 生成的 Integer 变量永远是不相等的,因为其内存地址是不同的;
2、Integer 变量和 int 变量比较时,只要两个变量的值是相等的,则结果为 true。因为包装类 Integer 和基本数据类型int 类型进行比较时,Java 会自动拆包装类为 int,然后进行比较,实际上就是两个 int 型变量在进行比较;
3、非 new 生成的Integer 变量和 new Integer() 生成的变量进行比较时,结果为 false。因为非 new 生成的 Integer 变量指向的是 Java 常量池中的对象,而 new Integer() 生成的变量指向堆中新建的对象,两者在内存中的地址不同;
4、对于两个非 new 生成的 Integer 对象进行比较时,如果两个变量的值在区间 [-128, 127] 之间,则比较结果为 true,否则为 false。Java 在编译 Integer i = 100 时,会编译成 Integer i =Integer.valueOf(100),而 Integer 类型的 valueOf 的源码如下所示:

public static Integer valueOf(int var0) { 
	return var0 >= -128 && var0 <= Integer.IntegerCache.high ? Integer.IntegerCache.cache[var0 + 128] : new Integer(var0);
 }

从上面的代码中可以看出:Java 对于 [-128, 127] 之间的数会进行缓存,比如:Integer i = 127,会将 127进行缓存,下次再写 Integer j = 127 的时候,就会直接从缓存中取出,而对于这个区间之外的数就需要 new 了。
包装类的缓存:
Boolean:全部缓存
Byte:全部缓存
Character:<= 127 缓存
Short:-128 — 127 缓存
Long:-128 — 127 缓存
Integer:-128 — 127 缓存
Float:没有缓存
Doulbe:没有缓存

13. 装箱和拆箱的区别

自动装箱是 Java 编译器在基本数据类型和对应得包装类之间做的一个转化。比如:把 int 转化成 Integer,double 转化成
Double 等等。反之就是自动拆箱。 原始类型:boolean、char、byte、short、int、long、float、double
封装类型:Boolean、Character、Byte、Short、Integer、Long、Float、Double

14. switch 语句能否作用在 byte 上,能否作用在 long 上,能否作用在 String 上?

在 switch(expr 1) 中,expr1 只能是一个整数表达式或者枚举常量。而整数表达式可以是 int 基本数据类型或者
Integer 包装类型。由于,byte、short、char 都可以隐式转换为
int,所以,这些类型以及这些类型的包装类型也都是可以的。而 long 和 String 类型都不符合 switch
的语法规定,并且不能被隐式的转换为 int 类型,所以,它们不能作用于 switch 语句中。不过,需要注意的是在 JDK1.7 版本之后
switch 就可以作用在 String 上了。

15. final、finally、finalize 的区别

final:用于声明属性、方法和类,分别表示属性不可变、方法不可覆盖、被其修饰的类不可继承;
finally:异常处理语句结构的一部分,表示总是执行;
finallize:Object类的一个方法,在垃圾回收时会调用被回收对象的finalize

16. == 和 equals 的区别?

如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象的地址值是否相等。
equals方法:用来比较两个对象的内容是否相等。注意:equals 方法不能用于比较基本数据类型的变量。如果没有对 equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址(很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等)。

17. 两个对象的 hashCode() 相同,则 equals() 也一定为 true 吗?

两个对象的 hashCode() 相同,equals() 不一定为 true。因为在散列表中,hashCode()
相等即两个键值对的哈希值相等,然而哈希值相等,并不一定能得出键值对相等【散列冲突】。

18. 为什么重写 equals() 就一定要重写 hashCode() 方法?

这个问题应该是有个前提,就是你需要用到 HashMap、HashSet 等 Java 集合,用不到哈希表的话,其实仅仅重写 equals()方法也可以。而工作中的场景是常常用到 Java 集合,所以 Java 官方建议重写 equals() 就一定要重写 hashCode()方法。 对于对象集合的判重,如果一个集合含有 10000 个对象实例,仅仅使用 equals() 方法的话,那么对于一个对象判重就需要比较10000 次,随着集合规模的增大,时间开销是很大的。但是同时使用哈希表的话,就能快速定位到对象的大概存储位置,并且在定位到大概存储位置后,后续比较过程中,如果两个对象的 hashCode 不相同,也不再需要调用 equals() 方法,从而大大减少了 equals() 比较次数。
所以从程序实现原理上来讲的话,既需要 equals() 方法,也需要 hashCode() 方法。那么既然重写了equals(),那么也要重写 hashCode() 方法,以保证两者之间的配合关系。
hashCode()与equals()的相关规定:
1、如果两个对象相等,则 hashCode 一定也是相同的;
2、两个对象相等,对两个对象分别调用 equals 方法都返回 true;
3、两个对象有相同的 hashCode 值,它们也不一定是相等的;
4、因此,equals 方法被覆盖过,则 hashCode方法也必须被覆盖;
5、hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。

19. & 和 && 的区别?

Java 中 && 和 & 都是表示与的逻辑运算符,都表示逻辑运输符 and,当两边的表达式都为 true 的时候,整个运算结果才为 true,否则为 false。
&&:有短路功能,当第一个表达式的值为 false 的时候,则不再计算第二个表达式;
&:不管第一个表达式结果是否为 true,第二个都会执行。除此之外,& 还可以用作位运算符:当 & 两边的表达式不是 Boolean
类型的时候,& 表示按位操作。

20. Java 中的参数传递时传值呢?还是传引用?

Java 的参数是以值传递的形式传入方法中,而不是引用传递。
当传递方法参数类型为基本数据类型(数字以及布尔值)时,一个方法是不可能修改一个基本数据类型的参数。
当传递方法参数类型为引用数据类型时,一个方法将修改一个引用数据类型的参数所指向对象的值。即使 Java
函数在传递引用数据类型时,也只是拷贝了引用的值罢了,之所以能修改引用数据是因为它们同时指向了一个对象,但这仍然是按值调用而不是引用调用。

21. Java 中的 Math.round(-1.5) 等于多少?

等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。

22. 如何实现对象的克隆?

(1)实现 Cloneable 接口并重写 Object 类中的 clone() 方法; (2)实现 Serializable
接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深克隆。

23. 深克隆和浅克隆的区别?

(1)浅克隆:拷贝对象和原始对象的引用类型引用同一个对象。浅克隆只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅克隆。
(2)深克隆:拷贝对象和原始对象的引用类型引用不同对象。深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝(例:JSON.parse()和 JSON.stringify(),但是此方法无法复制函数类型)。
补充: 深克隆的实现就是在引用类型所在的类实现 Cloneable接口,并使用 public 访问修饰符重写 clone 方法。
Java 中定义的 clone 没有深浅之分,都是统一的调用 Object的 clone 方法。为什么会有深克隆的概念?是由于我们在实现的过程中刻意的嵌套了 clone方法的调用。也就是说深克隆就是在需要克隆的对象类型的类中重新实现克隆方法 clone()。

24. 什么是 Java 的序列化,如何实现 Java 的序列化?

对象序列化是一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序。从字节流创建对象的相反的过程称为反序列化。而创建的字节流是与平台无关的,在一个平台上序列化的对象可以在不同的平台上反序列化。序列化是为了解决在对象流进行读写操作时所引发的问题。
序列化的实现:将需要被序列化的类实现 Serializable接口,该接口没有需要实现的方法,只是用于标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream 对象,接着使用 ObjectOutputStream 对象的 writeObject(Object obj) 方法可以将参数为 obj 的对象写出,要恢复的话则使用输入流。

25. 什么情况下需要序列化?

(1)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
(2)当你想用套接字在网络上传送对象的时候;
(3)当你想通过 RMI传输对象的时候。

26. Java 的泛型是如何工作的 ? 什么是类型擦除 ?

泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如:List\ 在运行时仅用一个List 来表示。这样做的目的,是确保能和 Java 5 之前的版本开发二进制类库进行兼容。
类型擦除:泛型信息只存在于代码编译阶段,在进入JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如 < T > 则会被转译成普通的 Object 类型,如果指定了上限如 < T extends String > 则类型参数就被替换成类型上限。

List list = new ArrayList();

1、两个 String 其实只有第一个起作用,后面一个没什么卵用,只不过 JDK7 才开始支持 List\list = newArrayList<> 这种写法。
2、第一个 String 就是告诉编译器,List 中存储的是 String对象,也就是起类型检查的作用,之后编译器会擦除泛型占位符,以保证兼容以前的代码。

27. 什么是泛型中的限定通配符和非限定通配符 ?

限定通配符对类型进行了限制。有两种限定通配符,一种是< ? extends T > 它通过确保类型必须是 T
的子类来设定类型的上界,另一种是< ? super T >它通过确保类型必须是 T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面 < ? > 表示了非限定通配符,因为 < ? 可以用任意类型来替代。

28. List 和 List 之间有什么区别 ?

这两个 List 的声明都是限定通配符的例子,List< ? extends T > 可以接受任何继承自 T 的类型的 List,而List< ? super T > 可以接受任何 T 的父类构成的 List。例如 List< ? extends Number > 可以接受 List< Integer > 或 List< Float > 。

Array 不支持泛型,要用 List 代替 Array,因为 List 可以提供编译器的类型安全保证,而 Array却不能。

29. Java 中的反射是什么意思?有哪些应用场景?

每个类都有一个 Class 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class对象。类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。也可以使用Class.forName(“com.mysql.jdbc.Driver”) 这种方式来控制类的加载,该方法会返回一个 Class 对象。
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。Class 和java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类:
(1)Field:可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段;
(2)Method :可以使用 invoke() 方法调用与 Method 对象关联的方法;
(3)Constructor :可以用 Constructor 创建新的对象。 应用举例:工厂模式,使用反射机制,根据全限定类名获得某个类的 Class 实例。

30. 反射的优缺点?

优点: 运行期类型的判断,class.forName() 动态加载类,提高代码的灵活度;
缺点:尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。
(1)性能开销 :反射涉及了动态类型的解析,所以 JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。
(2)安全限制 :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。
(3)内部暴露:由于反射允许代码执行一些在正常情况下不被允许的操作(比如:访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

31. Java 中的动态代理是什么?有哪些应用?

动态代理:当想要给实现了某个接口的类中的方法,加一些额外的处理。比如说加日志,加事务等。可以给这个类创建一个代理,故名思议就是创建一个新的类,这个类不仅包含原来类方法的功能,而且还在原来的基础上添加了额外处理的新功能。这个代理类并不是定义好的,是动态生成的。具有解耦意义,灵活,扩展性强。
动态代理的应用:Spring 的 AOP 、加事务、加权限、加日志。

32. 怎么实现动态代理?

首先必须定义一个接口,还要有一个 InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用它的 newInstance() 可以产生代理对象,其实它只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最后返回。
每一个动态代理类都必须要实现 InvocationHandler 这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由 InvocationHandler 这个接口的invoke 方法来进行调用。我们来看看 InvocationHandler 这个接口的唯一一个方法 invoke 方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy: 指代我们所代理的那个真实对象
method: 指代的是我们所要调用真实对象的某个方法的 Method 对象
args:指代的是调用真实对象某个方法时接受的参数
Proxy 类的作用是动态创建一个代理对象的类。它提供了许多的方法,但是我们用的最多的就是newProxyInstance 这个方法:

public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler) throws IllegalArgumentException

loader:一个 ClassLoader 对象,定义了由哪个 ClassLoader 对象来对生成的代理对象进行加载;
interfaces:一个 Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
handler:一个 InvocationHandler 对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个
InvocationHandler 对象上。 通过 Proxy.newProxyInstance 创建的代理对象是在 Jvm 运行时动态生成的一个对象,它并不是我们的 InvocationHandler 类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象。

33. static 关键字的作用?

(1)静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份;
(2)静态方法:静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字;
(3)静态语句块:静态语句块在类初始化时运行一次;
(4)静态内部类:非静态内部类依赖于外部类的实例,而静态内部类不需要。静态内部类不能访问外部类的非静态的变量和方法;
(5)初始化顺序:静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。

public static String staticField = "静态变量"; 
	static { 
		System.out.println("静态语句块"); ---- 1 
	} 
	public String field = "实例变量"; ---- 2 
	{
	 	System.out.println("普通语句块"); ----3 
	 } // 最后才是构造函数的初始化 
		 public InitialOrderTest() { 
	 		System.out.println("构造函数"); ----4 
		 }

初始化补充 存在继承的情况下,初始化顺序为:
1.父类(静态变量、静态语句块)
2.子类(静态变量、静态语句块)
3.父类(实例变量、普通语句块)
4.父类(构造函数)
5.子类(实例变量、普通语句块)
6.子类(构造函数)

34. super 关键字的作用?

1)访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。
(2)访问父类的成员:如果子类重写了父类的某个方法,可以通过使用 super 关键字来引用父类的方法实现。
(3)this 和 super不能同时出现在一个构造函数里面,因为 this 必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

35. 字节和字符的区别?

字节是存储容量的基本单位;
字符是数字、字母、汉字以及其他语言的各种符号;
1 字节 = 8个二进制单位,一个字符由一个字节或多个字节的二进制单位组成。

36. String 为什么要设计为不可变类?

在 Java 中将 String 设计成不可变的是综合考虑到各种因素的结果。主要的原因主要有以下三点:
(1)字符串常量池的需要:字符串常量池是 Java 堆内存中一个特殊的存储区域, 当创建一个 String
对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象;
(2)允许 String 对象缓存 HashCode:Java 中 String 对象的哈希码被频繁地使用, 比如在 HashMap 等容器中。字符串不变性保证了 hash码的唯一性,因此可以放心地进行缓存。这也是一种性能优化手段,意味着不必每次都去计算新的哈希码;
(3)String 被许多的 Java类(库)用来当做参数,例如:网络连接地址 URL、文件路径 path、还有反射机制所需要的 String 参数等, 假若 String 不是固定不变的,将会引起各种安全隐患。

37. String、StringBuilder、StringBuffer 的区别?

String:用于字符串操作,属于不可变类;
【补充:String 不是基本数据类型,是引用类型,底层用 char 数组实现的】
StringBuilder:与 StringBuffer 类似,都是字符串缓冲区,但线程不安全;
StringBuffer:也用于字符串操作,不同之处是 StringBuffer 属于可变类,对方法加了同步锁,线程安全
执行效率:StringBuilder > StringBuffer > String

38. String 字符串修改实现的原理?

当用 String 类型来对字符串进行修改时,其实现方法是首先创建一个 StringBuffer,其次调用 StringBuffer 的
append() 方法,最后调用 StringBuffer 的 toString() 方法把结果返回。

39. String str = “i” 与 String str = new String(“i”) 一样吗?

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;
而 String str=new String(“i”) 则会被分到堆内存中。

public class StringTest { 
	public static void main(String[] args) { 
		String str1 = "abc"; 
		String str2 = "abc"; 
		String str3 = new String("abc"); 
		String str4 = new String("abc"); 
		System.out.println(str1 == str2); // true 
		System.out.println(str1 == str3); // false 
		System.out.println(str3 == str4); // false 
		System.out.println(str3.equals(str4)); // true 
	} 
}

在执行 String str1 = “abc” 的时候,JVM会首先检查字符串常量池中是否已经存在该字符串对象,如果已经存在,那么就不会再创建了,直接返回该字符串在字符串常量池中的内存地址;如果该字符串还不存在字符串常量池中,那么就会在字符串常量池中创建该字符串对象,然后再返回。所以在执行String str2 = “abc”的时候,因为字符串常量池中已经存在“abc”字符串对象了,就不会在字符串常量池中再次创建了,所以栈内存中 str1 和 str2的内存地址都是指向 “abc” 在字符串常量池中的位置,所以 str1 = str2 的运行结果为 true。
而在执行 Stringstr3 = new String(“abc”) 的时候,JVM会首先检查字符串常量池中是否已经存在“abc”字符串,如果已经存在,则不会在字符串常量池中再创建了;如果不存在,则就会在字符串常量池中创建“abc” 字符串对象,然后再到堆内存中再创建一份字符串对象,把字符串常量池中的 “abc”字符串内容拷贝到内存中的字符串对象中,然后返回堆内存中该字符串的内存地址,即栈内存中存储的地址是堆内存中对象的内存地址。Stringstr4 = new String(“abc”) 是在堆内存中又创建了一个对象,所以 str 3 str4 运行的结果是 false。

40. String 类的常用方法都有那些?

indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。

41. final 修饰 StringBuffer 后还可以 append 吗?

可以。final 修饰的是一个引用变量,那么这个引用始终只能指向这个对象,但是这个对象内部的属性是可以变化的。

官方文档解释:once a final variable has been assigned, it always contains thesame value. If a final variable holds a reference to an object, thenthe state of the object may be changed by operations on the object,but the variable will always refer to the same object.
官方文档解释:一旦最后一个变量被分配,它总是包含同一值。如果final变量持有对某个对象的引用,那么该对象的状态可以通过对该对象的操作而改变。但是变量总是指向同一个对象。

42. Java 中的 IO 流的分类?说出几个你熟悉的实现类?

按功能来分:输入流(input)、输出流(output)。
按类型来分:字节流 和 字符流。
字节流:InputStream/OutputStream是字节流的抽象类,这两个抽象类又派生了若干子类,不同的子类分别处理不同的操作类型。具体子类如下所示:
字符流:Reader/Writer 是字符的抽象类,这两个抽象类也派生了若干子类,不同的子类分别处理不同的操作类型。
在这里插入图片描述

43. 字节流和字符流有什么区别?

字节流按 8 位传输,以字节为单位输入输出数据,
字符流按 16 位传输,以字符为单位输入输出数据。
但是不管文件读写还是网络发送接收,信息的最小存储单元都是字节。

44. BIO、NIO、AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统IO,它的特点是模式简单使用方便,并发处理能力低。同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

NIO:New IO 同步非阻塞 IO,是传统IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。NIO 是一种同步非阻塞的 I/O 模型,在 Java1.4中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它支持面向缓冲的,基于通道的 I/O 操作方法。NIO 提供了与传统BIO模型中的Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞 I/O 来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。

AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO的操作基于事件和回调机制。也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步 IO 的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。

45. 两个二进制数的异或结果是什么?

两个二进制数异或结果是这两个二进制数差的绝对值。表达式如下:a^b = |a-b|。 两个二进制 a 与 b 异或,即 a 和 b 两个数按位进行运算。如果对应的位相同,则为 0(相当于对应的算术相减),如果不同即为 1(相当于对应的算术相加)。由于二进制每个位只有两种状态,要么是 0,要么是 1,则按位异或操作可表达为按位相减取值相对值,再按位累加。

46.transient 关键字的作用?

对于不想进行序列化的变量,使用 transient 关键字修饰。
transient关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化。当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。

C# & SQL Server 实数据同步:7步轻松搞定,代码详解 数据同步是指在一个数据库中的数据发生变化,能够立即或近乎立即地将这些变化同步到另一个数据库中。这种同步可以是单向的(从源数据库同步到目标数据库),也可以是双向的(两个数据库互相同步)。通过本文的详细讲解和代码示例,相信你已经学会了如何使用C#和SQL Server实现数据库的实数据同步。实数据同步不仅可以提升系统的响应速度,还能确保数据的一致性和准确性。希望这篇教程对你有所帮助,期待你在C#编程中取得更大的成就!🌟✨如果你有任何问题或建议,欢迎在评论区留言交流! 阅读详情

相关推荐

Ghost卷积原理与构建YOLOv11的GhostNet变体

本文探讨了在边缘设备部署YOLOv11使用Ghost卷积进行模型轻量化的实践经验。针对Jetson Nano的4GB内存限制,作者通过替换Backbone中的3x3标准卷积为Ghost卷积,实现了参数减少28%、推理速度提升38%,仅损失1.1%mAP的优化效果。文章详细介绍了Ghost卷积的实现原理、在YOLOv11中的具体替换策略,以及训练调参和部署优化的关键技巧。作者强调轻量化是计算效率与模型性能的权衡,建议工程团队保留原模型和Ghost变体两个版本,根据实际需求灵活切换。Ghost卷积的核心价值在

as1225120794的博客 153

class文件中的方法表集合--method方法在class文件中是怎样组织的

0. 前言          了解JVM虚拟机原理是每一个Java程序员修炼的必经之路。但是由于JVM虚拟机中有很多的东西讲述的比较宽泛,在当前接触到的关于JVM虚拟机原理的教程或者博客中,绝大部分都是充斥的文字性的描述,很难给人以形象化的认知,看完之后感觉还是稀里糊涂的。          感于以上的种种,我打算把我在学习JVM虚拟机的过程中学到的东西,结合自己的理解,总结成《Java虚拟机...

luzhensmart的专栏 811

ANSYS仿真分析案例-汽车表面宽频噪声模拟(教程文档+模型数据).zip

ANSYS仿真分析案例-汽车表面宽频噪声模拟(教程文档+模型数据).zip

使用Synchronized关键字同步类方法

synchronized关键字有两种用法,一种是只用于方法的定义中,另外一种是synchronized块,我们不仅可以使用synchronized来同步一个对象变量,你也可以通synchronizedl来同步类中的静态方法和非静态方法。 synchronized块的语法如下: public void method() { synchronized(表达式) {

lonely_fireworks的专栏 7699

java两个类都有静态方法_Java一个类里面有两个用synchronized修饰的非静态方法,不同的线程中的实例访问这两个方法会发生什么?...

首先这个问题涉及到的是Java的对象锁。java的对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点...

weixin_39815286的博客 434

Java 多线程加锁的方式总结及对比

参考博文:http://www.cnblogs.com/handsomeye/p/5999362.html 一.Java多线程可以通过: 1. synchronized关键字 2. Java.util.concurrent包中的lock接口和ReentrantLock实现类 这两种方式实现加锁。 二.synchronized关键字加锁的缺陷: 如果一个代码块被s

u010842515的博客 7万+

JAVA基础

Java语言具有哪些特点? Java为纯面向对象的语言。它能够直接反应现实生活中的对象。 具有平台无关性。java利用Java虚拟机运行字节码,无论是在Windows、Linux还是MacOS等其它平台对Java程序进行编译,编译后的程序可在其它平台运行。 Java为解释型语言,编译器把Java代码编译成平台无关的中间代码,然后在JVM上解释运行,具有很好的可移植性。 Java提供了很多内置类库。如对多线程支持,对网络通信支持,最重要的一点是提供了垃圾回收器。 Java具有较好的安全性和健壮性。Java

LiLiYuan.的博客 273

Java基础常见面试题及详细答案(总结40个)

最近看到网上流传着各种面试经验及面试题,往往都是一大堆技术题目贴上去,但是没有答案。 为此我业余间整理了40道Java基础常见的面试题及详细答案,望各路大牛发现不对的地方不吝赐教,留言即可。 八种基本数据类型的大小,以及他们的封装类 引用数据类型 Switch能否用string做参数 equals与==的区别 自动装箱,常量池 Object有哪些公用方法 Java的四种引用,强弱软虚,用到的场景 Hashcode的作用 HashMap的hashcode的作用 为什么重载hashCod

ayouki123456的博客 4万+

经典Java基础面试题

经典Java基础面试题   Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同拥有全球最大的开发者专业社群。下面小编给大家介绍经典Java基础面试题,欢迎阅读! 经典Java基础面试题 篇1   1、如果main方法被声明为private会怎样?     能正常编译,但运行的候会提示”main方法不是public的”。     2、Java里的传引用和传值的区别是什么?     传引用是指传递的是地址而不是值本身,传值

java364100的博客 525

java基础面试题总结

可以吃的面食题,未完.......

菜就多练! 2025

Java基础面试题汇总

java基础面试题整理

个人博客,欢迎收藏。 1万+

面试题java基础

最近开始面试了,410面试了一家公司 针对自己薄弱的面试题库,深入了解下,也应付下面试

zbq1017的博客 1037

java基础面试题及答案_必会的java基础面试题及答案

Java语言是目前是世界上计算机中应用广泛的语言之一,如果想了解和学习javajava基础知识尤为重要。在一门编程语言中,了解其逻辑语法是首要任务之一,所以如果要进入java行业,有扎实的语法逻辑是必不可少的技能,就业面试中招聘者也少不了要考察你的基础知识。下面是整理的一些必会的java基础面试题及答案,希望对零基础的初学者和参加面试的朋友有所帮助。1.BOS与ERP是什么关系?ERP是企业管理...

weixin_39689428的博客 265

Java基础面试题50题

1,""空字符串的作用 package com.neuedu.nineteen; public class Test { public static void main(String[] args) { String s=""; for (char i = 'a'; i < 'd'; i++) { s=s+i;//输出...

渣渣的成长之路 6万+

java面试题纠错——java基础

java面试题纠错——java基础

m0_67403240的博客 565

Java Integer的缓存策略

Java5为Integer的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。 上面的规则默认适用于整数区间 -128 到 +127(这个整数区间可以通过启动应用的虚拟机参数修改:-XX:AutoBoxCacheMax)。这种Integer缓存策略仅在自动装箱(autoboxing)的候有用,使用构造器创建的Integer对象不能被缓存。...

weixin_33898233的博客 208

2020年Java基础面试必问一(内附代码详解)

** Java基础面试题 Java基础Java【集合】 Java【并发】 Java【网络】 Java【虚拟机】 ** 字节和字符的区别? 字节是存储容量的基本单位; 字符是数字、字母、汉字以及其他语言的各种符号; 1 字节 = 8 个二进制单位,一个字符由一个字节或多个字节的二进制单位组成 & 和 && 的区别 Java 中 && 和 & ...

老许的博客 1798

使用synchronized修饰静态方法和非静态方法有什么区别

1、Synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。 Java中每个对象都有一个锁,并且是唯一的。假设分配的一个对象空间,里面有多个方法,相当于空间里面有多个小房间,如果我们把所有的小房间都加锁,因为这个对象只有一把钥匙,因此同一间只能有一个人打开一个小房间,然后用完了还回去,再由JVM 去分配下一个获得钥匙的人。 情况1:同一个对象在两个线程中分别访问...

riemann_的博客 3887

8.3、java中方法的参数传递机制问题(基本数据类型传递与引用类型传递区别)

参考资料:java核心卷1 这篇文章主要介绍了Java中方法的参数传递机制 java方法参数传递机制原理 实现方法及操作注意事项 参数传递机制 对于程序设计语言来说,一般方法(函数)的参数传递有两种: 按值传递(按值调用) (call by value) 按引用传递(按引用调用) (call by reference) 按值传递:当将一个参数传递给一个方法,方...

hewenqing 794
上一篇: Jaspersoft Studio制作模板时导出的PDF中文不显示的问题原因及解决方法
下一篇: (CRON) info (No MTA installed, discarding output
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值