java面試| 精選基礎題
1.1定義
JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法。
1.2作用
①在運行時判斷任意一個對象所屬的類
②在運行時構造任意一個類的對象
③在運行時判斷任意一個類所具有的成員變量和方法(通過setAccessible()方法可訪問或修改private成員)
④在運行時調用任意一個對象的方法
1.3用法
首先得獲取class字節碼對象,再通過class對象可獲取類中的各種屬性和方法等
3種獲取class對象方法:
1.通過Object類的getClass方法
Class clazz = foo.getClass();
2.通過對象實例方法獲取對象
Class clazz = foo.class;
3.通過Class.forName方式
Class clazz = Class.forName("xx.xx.foo");//完整的類名,包括所在包
例子:
public class User {
private String name;
private int age;
private void speak(String name){ System.out.println("我的名字是:"+name); } public User(String name,int age)) { this.name = name; this.age = age; }
}
User user = new User("張三",25);
// 獲取User類中的所有方法
Method[] methods = User.class.getDeclaredMethods();
// 獲取User類中的所有屬性
Field[] fields = User.class.getDeclaredFields();
//遍歷User類的所有屬性
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
System.out.println(fields[i].getName()+":"+fields[i].get(user));
結果:
name:張三
age:25
(反射基本上可以獲取類中所有的信息,請自行谷歌)
1.4優缺點
優點:
1.能夠運行時動態獲取類的實例,大大提高了系統的靈活性和擴展性;
2.與java動態編譯相結合,可以實現無比強大的功能。
缺點:
1.使用反射的性能較低;
2.使用反射來說相對不安全;
3.破壞了類的封裝性,可以通過反射來獲取這個類的屬性和私有方法。
2.String、StringBuilder和StringBuffer的區別
存儲
String:字符串常量,對象一旦創建,不可更改
StringBuilder和StringBuffer:字符串變量,對象可更改
執行速度
String<StringBuffer<StringBuilder;
線程安全
String,StringBuilder是線程不安全的,StringBuffer是線程安全的。
適用範圍
String:適用於少量的字符串操作
StringBuilder:適用於單線程下,大量字符串操作
StringBuffer:適用多線程下,大量字符串操作
3.單例模式
作用
保證在Java程序中,某個類只有一個實例存在。
spring中的單例模式
spring生成對象默認是單例的,可將scope屬性設置為prototype改為多實例
<bean id="hi" class="com.test.Hi" init-method="init" scope="prototype">
適用場景
1.需要頻繁的進行創建和銷毀的對象;
2.創建對象時耗時過多或耗費資源過多,但又經常用到的對象;
3.工具類對象;
4.頻繁訪問數據庫或文件的對象。
4.Java 中 ++ 操作符是線程安全的嗎?
不是線程安全的操作。它涉及到多個指令,如讀取變量值,增加,然後存儲回內存,這個過程可能會出現多個線程交差。
5.== 與 equals 的區別
1.比較基本數據類型(int,float,double…)時,比較的是它們的值是否相等
2.比較引用類型(比如String類,自定義的User類等),比較的是引用所指向的對象是否相等, 即對象內存地址是否相同
equals
equals方法是由Object類提供的,可以由子類來進行重寫
Object類默認的實現如下:
public boolean equals(Object obj) {
return (this == obj);
}
默認的實現只有當對象和自身進行比較時才會返回true, 這個時候和 “==”是等價
的。
Java中很多類(String類 Date類 File類)等都對equals方法進行了重寫,這
裏拿常見的String類
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
這裏,從String的重寫equals方法可以看出,比較的是String的所存放內容是否相等
equals方法其實是交給開發者重寫,在自定義類裏,你想用它比較什麽都可以,只要你重寫它,所以我們並不能單純的說它是用來比較什麽的
6.數組在內存中如何分配
讀前須知:
棧:存放對象引用
堆:存放所有new出來的對象和數組
數組可以存放基本數據類型,可以存放引用類型。數組的引用存放於棧中,實際存放的對象在堆中。
可看以下代碼及分析:
// 存放基本數據類型
int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
// 存放自定義類型User
User[] userArr =new User[3];
User user1 = new User("張三");
User user2 = new User("李四");
user[0] = user1;
user[1] = user1;
user[2] = user2;
運行步驟分析:
存放基本數據類型
1.在棧中創建arr引用
2.在堆中創建長度3的int數組,並將其初始化,賦默認值0
3.將arr引用指向int數組
4.對int數組中每一個int值重新賦值
存放引用類型User
1.在棧中創建userArr引用
2.在堆中創建長度3的User數組,並將其初始化,賦默認值null
3.將userArr引用指向User數組
4.在棧中創建user1,user2引用
5.在堆中創建User("張三"),User("李四")對象
6.將user1,user2分別指向User("張三"),User("李四")
7.分別對User數組中的每一個User進行重新賦值,此時user[0]指向User("張三"),user[2]指向User("張三"),user[2]指向User("李四")
ps:這裏所說的指向是引用變量指向對象,即引用變量保存了對象在堆內存中的存儲地址
可看下圖,更好的理解:
圖片描述
ps:數組所存放的基本數據類型可能存放於堆中,也可能存放於方法區的常量池中,此處僅以堆中的基本數據類型為例。
java面試| 精選基礎題