8000 最最最常见Java面试题总结”系列第二周的文章。 · codeemma/Java-Guide@68de2b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 68de2b7

Browse files
committed
最最最常见Java面试题总结”系列第二周的文章。
1 parent 2dd259e commit 68de2b7

File tree

1 file changed

+209
-0
lines changed

1 file changed

+209
-0
lines changed
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
2+
### String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的?
3+
4+
#### String和StringBuffer、StringBuilder的区别
5+
6+
**可变性**
7+
 
8+
String类中使用字符数组:`private final char value[]`保存字符串,所以String对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[]value,这两种对象都是可变的。
9+
  
10+
11+
**线程安全性**
12+
13+
String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
14+
  
15+
16+
**性能**
17+
18+
每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
19+
20+
**对于三者使用的总结:**
21+
22+
- 如果要操作少量的数据用 = String
23+
- 单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
24+
- 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
25+
26+
#### String为什么是不可变的吗?
27+
简单来说就是String类利用了final修饰的char类型数组存储字符,源码如下图所以:
28+
29+
```java
30+
/** The value is used for character storage. */
31+
private final char value[];
32+
```
33+
34+
#### String真的是不可变的吗?
35+
我觉得如果别人问这个问题的话,回答不可变就可以了。
36+
下面只是给大家看两个有代表性的例子:
37+
38+
**1) String不可变但不代表引用不可以变**
39+
```java
40+
String str = "Hello";
41+
str = str + " World";
42+
System.out.println("str=" + str);
43+
```
44+
结果:
45+
```
46+
str=Hello World
47+
```
48+
解析:
49+
50+
实际上,原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。
51+
52+
**2) 通过反射是可以修改所谓的“不可变”对象**
53+
54+
```java
55+
// 创建字符串"Hello World", 并赋给引用s
56+
String s = "Hello World";
57+
58+
System.out.println("s = " + s); // Hello World
59+
60+
// 获取String类中的value字段
61+
Field valueFieldOfString = String.class.getDeclaredField("value");
62+
63+
// 改变value属性的访问权限
64+
valueFieldOfString.setAccessible(true);
65+
66+
// 获取s对象上的value属性的值
67+
char[] value = (char[]) valueFieldOfString.get(s);
68+
69+
// 改变value所引用的数组中的第5个字符
70+
value[5] = '_';
71+
72+
System.out.println("s = " + s); // Hello_World
73+
```
74+
75+
结果:
76+
77+
```
78+
s = Hello World
79+
s = Hello_World
80+
```
81+
82+
解析:
83+
84+
用反射可以访问私有成员, 然后反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。但是一般我们不会这么做,这里只是简单提一下有这个东西。
85+
86+
### 什么是反射机制?反射机制的应用场景有哪些?
87+
88+
#### 反射机制介绍
89+
90+
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
91+
92+
#### 静态编译和动态编译
93+
94+
- **静态编译:**在编译时确定类型,绑定对象
95+
- **动态编译:**运行时确定类型,绑定对象
96+
97+
#### 反射机制优缺点
98+
99+
- **优点:** 运行期类型的判断,动态加载类,提高代码灵活度。
100+
- **缺点:** 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多。
101+
102+
#### 反射的应用场景
103+
104+
反射是框架设计的灵魂。
105+
106+
在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关,例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。
107+
108+
举例:①我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;②Spring框架也用到很多反射机制,最经典的就是xml的配置模式。Spring 通过 XML 配置模式装载 Bean 的过程:1) 将程序内所有 XML 或 Properties 配置文件加载入内存中;
109+
2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息; 3)使用反射机制,根据这个字符串获得某个类的Class实例; 4)动态配置实例的属性
110+
111+
**推荐阅读:**
112+
113+
- [Reflection:Java反射机制的应用场景](https://segmentfault.com/a/1190000010162647?utm_source=tuicool&utm_medium=referral)
114+
- [Java基础之—反射(非常重要)](https://blog.csdn.net/sinat_38259539/article/details/71799078)
115+
### 什么是JDK?什么是JRE?什么是JVM?三者之间的联系与区别
116+
117+
这几个是Java中很基本很基本的东西,但是我相信一定还有很多人搞不清楚!为什么呢?因为我们大多数时候在使用现成的编译工具以及环境的时候,并没有去考虑这些东西。
118+
119+
**JDK:** 顾名思义它是给开发者提供的开发工具箱,是给程序开发者用的。它除了包括完整的JRE(Java Runtime Environment),Java运行环境,还包含了其他供开发者使用的工具包。
120+
121+
**JRE:** 普通用户而只需要安装JRE(Java Runtime Environment)来运行Java程序。而程序开发者必须安装JDK来编译、调试程序。
122+
123+
**JVM:** 当我们运行一个程序时,JVM负责将字节码转换为特定机器代码,JVM提供了内存管理/垃圾回收和安全机制等。这种独立于硬件和操作系统,正是java程序可以一次编写多处执行的原因。
124+
125+
**区别与联系:**
126+
127+
1. JDK用于开发,JRE用于运行java程序 ;
128+
2. JDK和JRE中都包含JVM ;
129+
3. JVM是java编程语言的核心并且具有平台独立性。
130+
131+
### 什么是字节码?采用字节码的最大好处是什么?
132+
133+
**先看下java中的编译器和解释器:**   
134+
135+
Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做`字节码`(即扩展名为`.class`的文件),它不面向任何特定的处理器,只面向虚拟机。每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。这也就是解释了Java的编译与解释并存的特点。
136+
137+
Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。
138+
139+
**采用字节码的好处:**   
140+
141+
Java语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。
142+
143+
### Java和C++的区别
144+
145+
我知道很多人没学过C++,但是面试官就是没事喜欢拿咱们Java和C++比呀!没办法!!!就算没学过C++,也要记下来!
146+
147+
- 都是面向对象的语言,都支持封装、继承和多态
148+
- Java不提供指针来直接访问内存,程序内存更加安全
149+
- Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。
150+
- Java有自动内存管理机制,不需要程序员手动释放无用内存
151+
152+
153+
### 接口和抽象类的区别是什么?
154+
155+
1. 接口的方法默认是public,所有方法在接口中不能有实现,抽象类可以有非抽象的方法
156+
2. 接口中的实例变量默认是final类型的,而抽象类中则不一定
157+
3. 一个类可以实现多个接口,但最多只能实现一个抽象类
158+
4. 一个类实现接口的话要实现接口的所有方法,而抽象类不一定
159+
5. 接口不能用new实例化,但可以声明,但是必须引用一个实现该接口的对象 从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
160+
161+
### 成员变量与局部变量的区别有那些?
162+
163+
1. 从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;但是,成员变量和局部变量都能被final所修饰;
164+
2. 从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存
165+
3. 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
166+
4. 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被final修饰但没有被static修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。
167+
168+
### 重载和重写的区别
169+
170+
**重载:** 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。   
171+
172+
**重写:** 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能重写该方法。
173+
174+
### 字符型常量和字符串常量的区别
175+
1) 形式上:
176+
字符常量是单引号引起的一个字符
177+
字符串常量是双引号引起的若干个字符
178+
2) 含义上:
179+
字符常量相当于一个整形值(ASCII值),可以参加表达式运算
180+
字符串常量代表一个地址值(该字符串在内存中存放位置)
181+
3) 占内存大小
182+
字符常量只占一个字节
183+
字符串常量占若干个字节(至少一个字符结束标志)
184+
185+
### 资源分享
186+
187+
精选互联网架构师视频、十多套精选实战项目视频、黑马内部视频、极客学院+北风网+黑马大数据工程师视频、5套精选Java面试指南视频等等。
188+
189+
**关注微信公众号“Java面试通关手册”回复关键字“1"即可免费领取!**
190+
191+
### 开源文档推荐
192+
Java-Guide: Java面试通关手册(Java学习指南)Java Interview Customs Manual (Java Study Guide)。star:1.9k。
193+
194+
Github地址:[https://github.com/Snailclimb/Java-Guide](https://github.com/Snailclimb/Java-Guide)
195+
196+
文档定位:一个专门为Java后端工程师准备的开源文档,相信不论你是Java新手还是已经成为一名Java工程师都能从这份文档中收获到一些东西。
197+
198+
参考:
199+
200+
https://segmentfault.com/a/1190000010162647?utm_source=tuicool&utm_medium=referral
201+
202+
https://blog.csdn.net/sinat_38259539/article/details/71799078
203+
204+
205+
206+
> 你若盛开,清风自来。 欢迎关注我的微信公众号:“Java面试通关手册”,一个有温度的微信公众号。公众号有大量资料,回复关键字“1”你可能看到想要的东西哦!
207+
208+
209+
![](https://user-gold-cdn.xitu.io/2018/7/5/1646a3d308a8db1c?w=258&h=258&f=jpeg&s=27034)

0 commit comments

Comments
 (0)
0