30.try-catch
public class Test {
public static void main(String[] args) {
System.out.println("return value of getValue(): " + getValue());
}
public static int getValue() {
int i = 1;
try {
return i;
} finally {
System.out.println("i : finally");
++i;
}
}
}
public static boolean get() {
try {
return false;
} finally {
return true;
}
}
在try中的return真正返回之前 ,會將false保存到一個臨時變量(假設爲var)中 ,然後執行finally,在執行finally子句的任何語句之前,會將var中的值取出,如果finally中沒有拋出異常或return、break、continue等語句,則在finally執行完後返回var (相當於返回去完成try中return的執行),如果finally中有return,var值會被覆蓋 ,返回結果是finllay子句中 return的值,如果是異常或break、continue等則執行相應的操作而不是返回。更詳細解釋參考JVM規範或《深入理解JAVA虛擬機(第二版)》。
其實相當於值傳遞
結果:1 true
31、返回一個n位隨機數
random.nextInt(n)
返回0~n 間的整數,包括0,不包括n
public static String getRandStr(int n){
Random random = new Random();
String sRand = "";
for (int i = 0; i < n; i++) {
String rand = String.valueOf(random.nextInt(10));
sRand += rand;
}
return sRand;
}
getRandStr(4)可返回一個4爲數
32、java中的main方法
String args[]保存的是 JAVA運行時傳遞給所運行類的參數,你這個類需要參數就傳,不需要就不傳.
public class TestMain{
public static void main(String args[]){
for(int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
}
接着用java TestMain first second運行
結果:
first
second
args實際上是個變量。它用來存儲你用命令後執行.class文件時後面跟的參數。args是可以變的,你可以變爲你喜歡的任意標識符。
普通方法其實可以不給,只是你在設計方法的時候要給一個不傳參數的方法。
注意:
1、其返回類型應該爲void
2、必須爲公共方法
a. public static void main()
b. public static void main(String[] string)
c. public static void main(string args)
d. static public int main(String[] args)
e.static void main(String[] args)
33、Map遍歷
for(Map.Entry<String, String> entry : map.entrySet()){
System.out.println(entry.getKey()+"--->"+entry.getValue());
}
34、for循環
for語句的格式爲:
for (初始化語句; 條件語句; 控制語句)
{
語句1 ;
語句2 ;
....
語句n ;
}
for 語句的執行順序是:首先執行“初始化語句”;然後測試“條件語句”;若條件成立,則執行語句1到語句n;然後執行“控制”語句;接着再測試條件語句是否成立,如果成立則重複執行以上過程,直至條件不成立時才結束for循環。
35、 Java 內存模型
淺析java內存模型--JMM(Java Memory Model)
2.1 Java 內存模型的基本原理
Java 內存模型,由於 Java 被設計爲跨平臺的語言,在內存管理上,顯然也要有一個統一的 模型。系統存在一個主內存 (Main Memory) , Java 中所有變量都儲存在主存中,對於所有線程都是共享的。每條線程都有自己的工作內存 (Working Memory) ,工作內存中保存的是主存中某些變量的拷貝,線程對所有變量的操作都是在工作內存中進行,線程之間無法相互直接訪問,變量傳遞均需要通過主存完成。
因爲當線程處於不同的cpu中時,它各自的變量保存在各自cpu的寄存器或者高速緩存中,這樣回事的變量對於其它線程暫時不可見。
2.2 Volatile 的內存工作原理
Volatile 是保證多個線程之間變量可見性的,也就是說一個線程對變量進行了寫操作,另外一個線程能夠獲取它最新的值。
它的工作原理是,它對寫和讀都是直接操作工作主存的。(這個可以通過操作字節碼看到)
2.3 Synchronized 的內存操作模型 :
Synchronized, 有兩層語義,一個是互斥,一個是可見性。在可見性上面,它的工作原理有點不同:當線程進入同步塊時,會從主存裏面獲取最新值,然後當線程離開同步塊時,再把變量的值更新到主存。
http://tomyz0223.iteye.com/blog/1001778
36.刪除一個文件夾內的所有文件和文件夾
File file = new File(imgPath);
if (!file.exists()) return;
deleteDirectory(file);
public void deleteDirectory(File path) {
if( path.exists() ) {
File[] files = path.listFiles();
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
}
37、關於JSP中的pageContext:
使用pageContext所設定的屬性對象,其共享範圍限於同一個JSP頁面,
使用request所設定的屬性對象,其在同一個request處理期間可以共享(包括forward給其它JSP頁面),
session對象所設定的屬性對象則限於同一個進程作用期間可以共享,
而application對象所設定的屬性,則在整個Web應用程序中的JSP頁面都可以共享。
38,Final的初始化
1. final修飾的成員變量沒有默認值
2. final初始化可以在三個地方
(1)聲明的時候初始化
(2)構造函數裏初始化
(3)要是沒有static修飾的話可以在非靜態塊裏初始化,要是有static修飾的話可以在靜態塊裏初始化
3. 使用final成員前要確保已經初始化,如果沒初始化,或者初始化多次,則無法通過編譯。
39、一些轉換技巧
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
//map轉換list
List<HandlerMapping> handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
//map判斷空
if (!matchingBeans.isEmpty())
//數組轉List (interceptors 數組)
interceptorList.addAll(Arrays.asList(this.interceptors));
//List轉指定對象數組
interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
40、java.lang.Number是所有基礎類型的父類
public abstract class Number implements java.io.Serializable {
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
public byte byteValue() {
return (byte)intValue();
}
public short shortValue() {
return (short)intValue();
}
}
public final class Long extends Number implements Comparable<Long>
public final class Integer extends Number implements Comparable<Integer>
41、JDK、JRE、JVM
JDK:Java Development ToolKit
Java開發工具包
JRE:Java Runtime Environment
Java運行環境
JVM:Java Virtual Machine
Java虛擬機
JMM:Java Memory Model
Java內存模型
JDK是SUN公司發佈的用於開發Java程序的工具包
在它的bin目錄下有很多工具,常見的包括:javac.exe,java.exe,javadoc.exe等(其中有很多都是用Java編寫的)各種版本的IDE工具也是需要使用JDK來完成編譯,打包,運行等各種功能的。
JRE顧名思義,java的運行環境
JDK是開發工具,在它的安裝目錄下包含了JRE目錄,其實在安裝JDK時(1.4版本以上),有一個安裝選項,如果勾上時,在Java的安裝目錄下會多一個JRE目錄,這裏的JRE與JDK下的JRE目錄基本上是完全一致的,那麼爲什麼需要兩個JRE呢?
前面已經提到過,JDK的bin目錄下的很多工具都是用Java編寫的,使用這些工具的時候也是需要運行環境的,通過這些.exe包裝器(這些包裝器提供了尋找tools.jar中的一些java類的快捷方法,不需要輸入一長串的包名和類名)來使用那些工具時,java會自動尋找父目錄下的JRE,所以在這裏放置了JRE。
JVM:Java虛擬機,在window下作爲動態連接庫(jvm.dll)存在,用於解釋執行Java字節碼。jvm.dll文件路徑爲:jre7\bin\server
可以把它理解成是專門用來執行Java程序的一臺機器。也就是說JVM提供了Java執行的硬件平臺。JVM上執行的代碼都存放在.CLASS文件中。JVM只執行字節碼文件。
==================================================================
Java的跨平臺如何體現:
JVM也是一個軟件,不同的平臺有不同的版本。我們編寫的Java源碼,編譯後會生成一種 .class 文件,稱爲字節碼文件。Java虛擬機就是負責將字節碼文件翻譯成特定平臺下的機器碼然後運行。也就是說,只要在不同平臺上安裝對應的JVM,就可以運行字節碼文件,運行我們編寫的Java程序。
注意:編譯的結果不是生成機器碼,而是生成字節碼,字節碼不能直接運行,必須通過JVM翻譯成機器碼才能運行。不同平臺下編譯生成的字節碼是一樣的,但是由JVM翻譯成的機器碼卻不一樣。
所以,運行Java程序必須有JVM的支持,因爲編譯的結果不是機器碼,必須要經過JVM的再次翻譯才能執行。即使你將Java程序打包成可執行文件(例如 .exe),仍然需要JVM的支持。
注意:跨平臺的是Java程序,不是JVM。JVM是用C/C++開發的,不能跨平臺,不同平臺下需要安裝不同版本的JVM。
42、finalize()
Java 技術允許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。
這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。
finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的。
垃圾收集器只知道釋放那些由new分配的內存,所以不知道如何釋放對象的“特殊”內存。爲解決這個問題
Java提供了一個名爲finalize()的方法,它的工作原理應該是這樣的:一旦垃圾收集器準備好釋放對象佔用的存儲空間,它首先調用finalize(),而且只有在下一次垃圾收集過程中,纔會真正回收對象的內存。
所以如果使用finalize(),就可以在垃圾收集期間進行一些重要的清除或清掃工作(如關閉流等操作)。但JVM(Java虛擬機)不保證此方法總被調用。
43、原子操作AtomicInteger
public class AtomicLong extends Number
implements Serializable
不使用synchronized關鍵字,AtomicInteger通過另一種線程安全的方法實現加減操作。
AtomicInteger爲什麼能夠達到多而不亂,處理高併發應付自如呢?
這是由硬件提供原子操作指令實現的,這裏面用到了一種併發技術:CAS。在非激烈競爭的情況下,開銷更小,速度更快。
Java.util.concurrent中實現的原子操作類包括:
AtomicBoolean、AtomicInteger、AtomicIntegerArray、AtomicLong、AtomicReference、AtomicReferenceArray。
J2SE 5.0提供了一組atomic class來幫助我們簡化同步處理。
基本工作原理是使用了同步synchronized的方法實現了對一個long, integer, 對象的增、減、賦值(更新)操作. 比如對於++運算符, AtomicInteger可以將它持有的integer 能夠atomic 地遞增。在需要訪問兩個或兩個以上 atomic變量的程序代碼(或者是對單一的atomic變量執行兩個或兩個以上的操作)通常都需要被synchronize以便兩者的操作能夠被當作是一個atomic的單元。
addAndGet(long delta)
//以原子方式將給定值添加到當前值。
getAndSet() :
//設置新值,返回舊值.
compareAndSet(expectedValue, newValue) :
//如果當前值 == 預期值,則以原子方式將該值設置爲給定的更新值
//如果更新成功,返回true, 否則返回false
//換句話可以這樣說: 將原子變量設置爲新的值, 但是如果從我上次看到的這個變量之後到現在被其他線程修改了(和我期望看到的值不符), 那麼更新失敗
/* 單線程下, compareAndSet返回永遠爲true,
* 多線程下, 在與result進行compare時, counter可能被其他線程set了新值, 這時需要重新再取一遍再比較,
* 如果還是沒有拿到最新的值, 則一直循環下去, 直到拿到最新的那個值
*/
int incrementAndGet()
以原子方式將當前值加 1。
爲了提高性能,AtomicLong等類在實現同步時,沒有用synchronized關鍵字,而是直接使用了最低層(本地c語言實現代碼)來完成的,
因而你是看不到用synchronized關鍵字的.
比如:AtomicLong類中原子操作方法:
public final boolean compareAndSet(long expect, long update) ;
就是直接使用SUN公司低層本地代碼的原子方法(native方法):
public final native boolean compareAndSwapLong(...)來實現的.
Example:
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
/*
* ava.util.concurrent中實現的原子操作類包括:
AtomicBoolean、AtomicInteger、AtomicIntegerArray、AtomicLong、AtomicReference、
AtomicReferenceArray。
*
*/
public class AtomicOperationDemo {
static AtomicInteger count=new AtomicInteger(0);
public static class AddThread implements Runnable{
@Override
public void run() {
for(int k=0;k<1000;k++){
count.incrementAndGet();
}
}
}
public static void AtomicIntShow(){
System.out.println("AtomicIntShow() enter");
ExecutorService threadpool = Executors.newFixedThreadPool(10);
//開100個線程
for(int k=0;k<100;k++){
threadpool.submit(new AddThread());
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* output
* AtomicIntShow() enter
* result of acumulated sum=100000
* AtomicIntShow() exit
*/
System.out.println("result of acumulated sum="+count);
threadpool.shutdown();
System.out.println("AtomicIntShow() exit");
return ;
}
}
public class Maintest {
public static void main(String[] args) {
AtomicOperationDemo.AtomicIntShow();
}
}
結果:
/* output
* AtomicIntShow() enter
* result of acumulated sum=100000
* AtomicIntShow() exit
*/
44、Object、String類中equals方法的不同
StringBuffer / StringBuilder的equals方法都是繼承的Object方法
String類中對equals方法進行了重寫
Object類的equals方法的實現:
public boolean equals(Object obj) {
return (this == obj);
}
Object中的equals就是用==來比較當前對象和傳入的參數的。
再看看String的equals實現:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
它去比較內容了。
再看StringBuilder,在其源碼裏沒有發現equals方法,那麼它就繼承了Object的實現,用==來比較傳進來的參數。
我們看到equals是個實例方法(非static),實例方法是可以被子類重寫而去實現自己想要的行爲的,因此,不能輕易的說equals就是比較內容的,其行爲是特定於實現的。但==確實是比較地址的。因爲java中不支持(至少現在不支持)運算符重載,我們不能改變==的含義,其行爲是固定死的。
記得下次不要說“==比較地址,equals比較內容”這樣的話了,如果要說,也在前面加上特定的條件,如“如果比較String”,勿斷章取義。
45、不借助中間變量交換元素
a = a + b b = a - b a = a - b
46.UUID
UUID(Universally Unique Identifier)
全局唯一標識符
是指在一臺機器上生成的數字,是1.5中新增的一個類,在java.util下,用它可以產生一個號稱全球唯一的ID
按照開放軟件基金會(OSF)制定的標準計算,用到了以太網卡地址、納秒級時間、芯片ID碼和許多可能的數字。
由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關,如果你在生成一個UUID之後,過幾秒又生成一個UUID,則第一個部分不同,其餘相同),時鐘序列,全局唯一的IEEE機器識別號(如果有網卡,從網卡獲得,沒有網卡以其他方式獲得),UUID的唯一缺陷在於生成的結果串會比較長。
JDK1.5
如果使用的JDK1.5的話,那麼生成UUID變成了一件簡單的事,以爲JDK實現了UUID:
java.util.UUID,直接調用即可.
String s = UUID.randomUUID().toString();
UUID是由一個十六位的數字組成,表現出來的形式例如
550E8400-E29B-11D4-A716-446655440000
47、獲取隨機數
法1:
int num = getRandom(1000);
public static int getRandom(int num) {
return (int) Math.round(Math.random() * num);
}
API:
double java.lang.Math.random()
//Returns a double value greater than or equal to 0.0 and less than 1.0
long java.lang.Math.round(double a)
法2:
Random random = new Random();
int num = random.nextInt(50);
API:
int java.util.Random.nextInt(int n)
//Returns a int value between 0 (inclusive) and the specified value (exclusive),
公共方法:
public static final String allChar = "023456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ";
public static final String numberChar = "023456789";
/*
* 獲取隨機字符串
*/
public static String generateString(int length){ //參數爲返回隨機數的長度
StringBuffer sb = new StringBuffer();
Random random = new Random();
for (int i = 0; i < length; i++) {
sb.append(allChar.charAt(random.nextInt(allChar.length())));
}
return sb.toString();
}
public static String generateNumber(int length){ //參數爲返回隨機數的長度
StringBuffer sb = new StringBuffer();
Random random = new Random();
for (int i = 0; i < length; i++) {
sb.append(numberChar.charAt(random.nextInt(numberChar.length())));
}
return sb.toString();
}
48、request.getParameterMap()
在servlet中GET請求可以通過HttpServletRequest的getRequestURL方法和getQueryString()得到完整的請求路徑和請求所有參數列表,
POST的需要getParameterMap()方法遍歷得到,
不論GET或POST都可以通過getRequestURL+getParameterMap()來得到請求完整路徑
request.getParameterMap()的返回類型是Map類型的對象,也就是符合key-value的對應關係,但這裏要注意的是,value的類型是String[],而不是String.
得到jsp頁面提交的參數很容易,但通過它可以將request中的參數和值變成一個map,以下是將得到的參數和值
打印出來,形成的map結構:map(key,value[]),即:key是String型,value是String型數組。
例如:request中的參數t1=1&t1=2&t2=3
形成的map結構:
key=t1;value[0]=1,value[1]=2
key=t2;value[0]=3
如果直接用map.get("t1"),得到的將是:Ljava.lang.String; value只所以是數組形式,就是防止參數名有相同的
情況。
public class ParamsUitl {
public static Map<String, String> getParamsMap(HttpServletRequest request) {
Map<String,String> params = new HashMap<String,String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
valueStr = new String(valueStr);
params.put(name, valueStr);
}
return params;
}
}
49.特殊字符過濾
private String formatString(String oldStr){
String regEx="[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&*()——+|{}【】‘;:”“’。,、?\r\n|\r|\n|\n\r]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(oldStr);
return m.replaceAll("").trim();
}
50.整數相除保留小數
java中,當兩個整數相除時,由於小數點以後的數字會被截斷,運算結果將爲整數,此時若希望得到運算結果爲浮點數,必須將兩整數其一或是兩者都強制轉換爲浮點數。
例如:
(float)a/b // 將整數其中一個強制轉換爲浮點數,再與另一個整數相除
a/(float)b
(float)a/(float)b // 將兩個整數同時強制轉換爲浮點數後再相除
- float num= (float)2/3;
- DecimalFormat df = new DecimalFormat("0.00");//格式化小數
- String s = df.format(num);//返回的是String類型
51、new File(File parent, String child)
File home = new File(getCatalinaBase());
File conf = new File(home, "conf");
File properties = new File(conf, "catalina.properties");
parent下的目錄或文件 的File對象
52、爲啥final類型的map或者arraylist可以修改數據 而final類型的String變量不可以修改數據呢
比如
final Map map =new HashMap(); 可以往map裏put數據
final List list =new ArrayList(); 可以往list裏add數據
但是 final String s =“123”; 然後s就不可修改數據了
同樣是final 爲啥map和list可以修改 但是string不可以修改呢
答:
final 只是表示引用不可以修改,如果你先寫final Map map =new HashMap(); 再寫 map =new HashMap(); 同樣會報錯
map和list只是個地址,final的意思是地址不能改,但是地址指向的內容當然可以改。
final的意思是一個已初始化的變量不能再指向另外的值/對象
53、BigDecimal保留2位小數
public class test1_format {
public static void main(String[] args) {
BigDecimal decimal = new BigDecimal("1.12345");
System.out.println(decimal);
BigDecimal setScale = decimal.setScale(4,BigDecimal.ROUND_HALF_DOWN);
System.out.println(setScale);
BigDecimal setScale1 = decimal.setScale(4,BigDecimal.ROUND_HALF_UP);
System.out.println(setScale1);
}
}
..
54、訂單的動態字符串
if(ret.getCode() == 0){
if(response.exists("lOrderId") && response.exists("Id")){
//整理訂單商品
OrderUtil.formatOrderProducts(response.get("lOrderId"));
result.setIntegerValue("orderId", ..);
...
result.setIntegerValue("code", 0);
}
}else{
result.setIntegerValue("code", -10);
}
/*
* 整理訂單
*/
public static void formatOrderProducts(Integer orderId) {
itemsGood = getOrderProducts(orderId);
if(itemsGood != null){
StringBuffer strOrderGoodsList = new StringBuffer("[");
int i=1;
for(T itemGood : itemsGood){
strOrderGoodsList.append("{\"lOrderProductId\":" + itemGood.get("lBuyerOrderProductId"));
if(itemGood.exists("lBuyerId")){
strOrderGoodsList.append(",\"lBuyerId\":" + itemGood.get("lBuyerId"));
}
strOrderGoodsList.append(",\"lGoodsId\":" + itemGood.get("nProductId") + "," +
"\"strLogoURL\":\"" + itemGood.getStringValue("strLogoURL") + "\","+
"\"nState\":\"" + itemGood.get("nState") + "\","+
"\"nType\":\"" + itemGood.get("nType") + "\","+
"\"nComponent\":\"" + itemGood.get("nComponent") + "\"," +
"\"nIsValue\":\"" + itemGood.get("nIsValue") + "\",");
if(itemGood.exists("nRefundBackId")){
if(itemGood.get("nRefundBackId") > 0){
strOrderGoodsList.append("\"nRefundId\":\"" + itemGood.get("nRefundBackId") + "\"," + "\"nRefundType\":\"" + itemGood.get("nRefundType") + "\"," + "\"nRefundState\":\"" + itemGood.get("nOrderState") + "\",");
if(itemGood.exists("strTrackingCode"))
strOrderGoodsList.append("\"strTrackingCode\":\"" + itemGood.getStringValue("strTrackingCode") + "\"," );
}
}
strOrderGoodsList.append("\"strGoodsTitle\":\"" + itemGood.getStringValue("strProductTitle") + "\",\"nPrice\":\"" + itemGood.getStringValue("nMallPrice") +
"\",\"nCount\":" + itemGood.get("nQuantity") + ",\"lCategoryId\":\"" + itemGood.getStringValue("nProductCategory") + "\"}");
if (itemsGood.length > i) {
strOrderGoodsList.append(",");
}
i++;
}
strOrderGoodsList.append("]");
//更新主訂單中strOrderGoodsList字符串
updateOrderGoodsList(orderId,strOrderGoodsList.toString());
}
}
55、如何逆轉字符串
a、org.apache.commons.lang.StringUtils
StringUtils.reverse 本質還是第二種方法
b、new StringBuffer(res).reverse()
c、利用最簡單的交換兩個變量的值的方法,即 t = a, a = b, b = t這樣的方式
char* Reverse(char* str, int length)
{
for (int i = 0; i < length / 2; ++i)
{
str[length] = str[i];
str[i] = str[length - 1 - i];
str[length - 1 - i] = str[length];
}
str[length] = 0;
return str;
}
56、JAVA中有那些類是Final的??
https://blog.csdn.net/dgeek/article/details/53425192
所有包裝類:Boolean,Character,Short,Integer,Long,Float,Double,Byte,Void
字符串類:String,StringBuilder,StringBuffer
系統類:Class,System,RuntimePermission,Compiler
數學類:Math,StrictMath
其他:Character.UnicodeBlock,ProcessBuilder,StackTraceElement
57、簡要描述String、StringBuffer、StringBuilder的區別
可變性、線程安全、性能三個方面
可變性
String類,final類,使用字符數組保存字符串,private final char value[],所以string對象是不可變的。
StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,char[] value,這兩種對象都是可變的。
線程安全性
String中的對象是不可變的,也就可以理解爲常量,線程安全。
StringBuffer對方法加了同步鎖synchronized或者對調用的方法加了同步鎖,所以是線程安全的。
StringBuilder並沒有對方法進行加同步鎖,所以是非線程安全的。
性能
每次對String 類型進行改變的時候,都會生成一個新的 String 對象,然後將指針指向新的 String 對象。StringBuffer每次都會對 StringBuffer 對象本身進行操作,而不是生成新的對象並改變對象引用。相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。
58、char型變量中能不能存貯一箇中文漢字?爲什麼?
在C語言中,char類型佔1一個字節,而漢子佔2個字節,所以不能存儲。
在Java中,char類型佔2個字節,而且Java默認採用Unicode編碼,一個Unicode碼是16位,所以一個Unicode碼佔兩個字節,Java中無論漢子還是英文字母都是用Unicode編碼來表示的。所以,在Java中,char類型變量可以存儲一箇中文漢字。
59、TOMCAT最大鏈接數多少?
設置tomcat下conf文件夾的server.xml文件
maxThreads="150" 表示最多同時處理150個連接
minSpareThreads="25" 表示即使沒有人使用也開這麼多空線程等待
maxSpareThreads="75" 表示如果最多可以空75個線程,例如某時刻有80人訪問,之後沒有人訪問了,則tomcat不會保留80個空線程,而是關閉5個空的。
acceptCount="100" 當同時連接的人數達到maxThreads時,還可以接收排隊的連接,超過這個連接的則直接返回拒絕連接。
60、java.util.Date和java.sql.Date的區別和相互轉化
共同點:都有getTime方法返回毫秒數,可以直接構建
不同點:
1、java.sql.Date是針對SQL語句使用的,它只包含日期而沒有時間部分,一般在讀寫數據庫的時候用,PreparedStament的setDate()的參數和ResultSet的getDate()方法的都是java.sql.Date
2、java.util.Date是在除了SQL語句的情況下面使用,一般是日常日期字段
3、java.util.Date 是 java.sql.Date 的父類,即:繼承關係:java.lang.Object --》 java.util.Date --》 java.sql.Date
相互轉化:
//java.sql.Date轉爲java.util.Date
java.sql.Date date=new java.sql.Date();
java.util.Date d=new java.util.Date (date.getTime());
//java.util.Date轉爲java.sql.Date
java.util.Date utilDate=new Date();
java.sql.Date sqlDate=new java.sql.Date(utilDate.getTime());
java.util.Date utilDate=new Date();
61、覆蓋hashCode()方法的原則:
一定要讓那些我們認爲相同的對象返回相同的hashCode值
儘量讓那些我們認爲不同的對象返回不同的hashCode值,否則,就會增加衝突的概率。
儘量的讓hashCode值散列開(兩值用異或運算可使結果的範圍更廣)
62、
...
易錯題:
1、
int j = 0;
j = j++;
System.out.println(j);
沒見過此題的人,大部分人可能得到的結果是:1。 然而,運行的結果會令您徹底失望。這是什麼原因呢?原來Java編譯器處理後綴++或--時是這麼處理的:java的編譯器在遇到j++和j- -的時候會重新爲變量運算分配一塊內存空間,以存放原始的值,而在完成了賦值運算之後,將這塊內存釋放掉。即JAVA先將j的值保存到臨時內存空間中,然 後處理++,即原來的j加1,此時原來的j變成1,然後再執行賦值,將內存空間中所存放的原來的值賦回給j,所以j仍然是0。C#和Java的結果是一樣 的。
相反,C/C++不是這麼處理的:C中是通過寄存器作中轉先把j的值賦給它本身,再執行++的操作,這樣結果就是1了。
2、
String a = "abc";
String b = "abc";
System.out.println("====>"+ a==b ); //"+"的優先級比"=="高,實際比較的是"====>abc"與abc false
System.out.println("====>"+ (a==b) ); //true
3、一眼能說出它的結果
public class MainTest {
public static void main(String[] args) {
String s = null;
s = s+"word";
System.out.println("hello " +s);
}
}
結果:hello nullword
String s = null;
//s = s+"word";
System.out.println("hello " +s);
//結果:hello null
String s = null 與 s="" 有什麼區別?
s是一個String類的引用,null表示它不指向任何字符串對象,""表示s指向一個長度爲0的字符串對象。如果調用s.length()之類的方法,s爲null時會拋出NullPointerException,而""則能進行正常的計算。
抽象類中可以有抽象方法和非抽象方法 !
構造方法可以被重載,但不可以被重寫
數組沒有 length() 這個方法,有 length 的屬性。 String 有有 length() 這個方法。
Scanner scanner = new Scanner(System.in);
String temp = scanner.nextLine();
System.out.println("temp=="+temp);
// 輸入。。。
new String(name.getBytes("iso-8859-1"),"utf-8");
其他:
java類成員變量在沒有賦值的時候會賦以默認值,其它局部變量是不能夠享受這種待遇的。