其餘:首先感謝知了堂-陽哥在學習道路上長達一年的陪伴,也很慶幸在知了堂碰見鑫鑫.html
若有侵權或者錯誤,請務必留言,萌新感謝大佬的指點.java
用FruitFactory工廠類建立Apple或者Grape類,引用了Java中的反射機制(在運行期動態加載類)mysql
1 package staticfactory; 2 3 public class FruitFactory { 4 public static Fruit getFruit(String type){ 5 Fruit f = null; 6 try { 7 // 經過反射機制在運行期建立實例 8 f = (Fruit)Class.forName("staticfactory." + type).newInstance(); 9 } catch(Exception e){ 10 System.out.print("目前沒法生產這種水果"); 11 } 12 return f; 13 } 14 15 public static void main(String[] args) { 16 Fruit f = FruitFactory.getFruit("Apple"); 17 f.say(); 18 } 19 }
1 package staticfactory; 2 3 public class Apple implements Fruit { 4 5 @Override 6 public void say() { 7 System.out.println("I am Apple"); 8 } 9 10 } 11 12 13 package staticfactory; 14 15 public class Apple implements Fruit { 16 17 @Override 18 public void say() { 19 System.out.println("I am Apple"); 20 } 21 22 }
1 package staticfactory; 2 3 public interface Fruit { 4 public void say(); 5 }
大優點:程序員
主要缺點:sql
在NutritionFacts中聲明一個靜態內部類Builder,利用Builder類的相似setter方法(會返回當前Builder對象)來爲Builder類初始化,所有初始化後利用build()方法返回一個Nutrition對象.數據庫
Nutrition中有一個私有構造方法,它經過深拷貝Builder的屬性來完成初始化.編程
1 package telescopingConstructor; 2 3 public class NutritionFacts { 4 // required 5 private final int servingSize; 6 private final int servings; 7 8 // optional 9 public final int calories; 10 public final int fat; 11 public final int sodium; 12 public final int carbohydrate; 13 14 public static class Builder { 15 // required 16 private final int servingSize; 17 private final int servings; 18 19 // optional 20 public int calories; 21 public int fat; 22 public int sodium; 23 public int carbohydrate; 24 25 public Builder(int servingSize, int servings) { 26 super(); 27 this.servingSize = servingSize; 28 this.servings = servings; 29 } 30 31 public Builder calories(int val){ 32 this.calories = val; 33 return this; 34 } 35 36 public Builder fat(int val) { 37 this.fat = val; 38 return this; 39 } 40 41 public Builder carbohydrate(int val){ 42 this.carbohydrate = val; 43 return this; 44 } 45 46 public Builder sodium(int val) { 47 this.sodium = val; 48 return this; 49 } 50 51 public NutritionFacts build(){ 52 return new NutritionFacts(this); 53 } 54 } 55 56 private NutritionFacts(Builder builder){ 57 servingSize = builder.servingSize; 58 servings = builder.servings; 59 calories = builder.calories; 60 fat = builder.fat; 61 sodium = builder.sodium; 62 carbohydrate = builder.carbohydrate; 63 } 64 65 @Override 66 public String toString(){ 67 return servingSize + " " + servings + " " + calories + " " + fat + " " + sodium + " " + carbohydrate; 68 } 69 70 public static void main(String[] args) { 71 NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build(); 72 System.out.println(cocaCola.toString()); 73 } 74 75 }
優點:segmentfault
劣勢:數組
Singleton指僅僅被實例化一次的類.緩存
1 public class Sengleton_Lyze { 2 //1,構造方法私有化 3 private Sengleton_Lyze(){ 4 } 5 6 //2,建立類的位惟一實例,private static 修飾 7 private static Sengleton_Lyze instance; 8 9 //3,提供獲取實例的方法,public static 修飾 10 public static Sengleton_Lyze getInstance(){ 11 if (instance==null) { 12 instance=new Sengleton_Lyze(); 13 } 14 return instance; 15 } 16 }
1 /** 2 * 單例模式Sengleton 3 * 試用實際場合:有些對象只須要一個就夠了。 4 * 做用:保證整個實際應用程序中某個實例有且只有一個 5 * 類別:餓漢模式,懶漢模式 6 * 區別:餓漢模式的特色,加載類時比較慢,獲取比較慢。線程安全的。 7 * 8 * 9 */ 10 public class Sengleton_Hunger { 11 //1,構造方法私有化,不容許外接直接建立對象 12 private Sengleton_Hunger(){ 13 } 14 //2,建立類的惟一實例,使用private static 修飾 15 private static Sengleton_Hunger instance = new Sengleton_Hunger(); 16 17 //3,獲取這個實例的方法 18 public static Sengleton_Hunger getInstance(){ 19 return instance; 20 } 21 22 }
1 public class Test { 2 public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 3 //餓漢模式 4 Constructor sengleton_Hunger = Sengleton_Hunger.class.getDeclaredConstructor(); 5 sengleton_Hunger.setAccessible(true); 6 Sengleton_Hunger s1= (Sengleton_Hunger) sengleton_Hunger.newInstance(); 7 Sengleton_Hunger s2= (Sengleton_Hunger) sengleton_Hunger.newInstance(); 8 if (s1==s2) { 9 System.out.println("true"); 10 }else { 11 System.out.println("false"); 12 } 13 14 //懶漢模式 15 Constructor sengleton_Lyze = Sengleton_Lyze.class.getDeclaredConstructor(); 16 sengleton_Lyze.setAccessible(true); 17 Sengleton_Lyze s3= (Sengleton_Lyze) sengleton_Lyze.newInstance(); 18 Sengleton_Lyze s4= (Sengleton_Lyze) sengleton_Lyze.newInstance(); 19 if (s1==s2) { 20 System.out.println("同樣的"); 21 }else { 22 System.out.println("不一樣的"); 23 } 24 } 25 26 } 27 28 結果 29 false 30 不一樣的
1 public class Sltn { 2 private static Sltn s = null; 3 private static boolean flag = true; 4 5 private Sltn(){ 6 System.out.println("flag:" + flag); 7 if(flag){ 8 flag = !flag; 9 }else{ 10 try { 11 throw new Exception("duplicate instance create error!" + Sltn.class.getName()); 12 } catch (Exception e) { 13 e.printStackTrace(); 14 } 15 } 16 } 17 18 public static Sltn getInstance(){ 19 if(null == s){ 20 s = new Sltn(); 21 } 22 return s; 23 } 24 }
以上摘自:https://www.cnblogs.com/ybbzbb/p/5524261.html
1 package useenum; 2 3 public enum Elvis { 4 INsTANCE; 5 6 public void leaveTheBuilding(){ 7 8 } 9 }
在缺乏顯示構造器的狀況下,編譯器會自動提供一個共有的,無參的缺省構造器.對於用戶而言,這個構造器與其餘的構造器沒有任務區別.
企圖經過將類作成抽象類來強制該類不可被實例化,這是行不通的.該類能夠被子類化,而且該子類也能夠被實例化.這樣作甚至會誤導用戶,覺得這種類是專門爲了繼承而設計的.
添加一個私有構造器,來阻止在外部被實例化.
1 public class UtilityClass { 2 // Suppress default constructor for noninstantiability 3 private UtilityClass() { 4 throw new AssertionError(); 5 } 6 7 // Remainder omitted 8 }
以上2018/10/8 23:19更新
通常來講,最好能重用對象而不是在每次須要的時候就建立一個相同功能的新對象.重用方式既快速,又流行.
1 import java.sql.Connection; 2 import java.sql.DriverManager; 3 import java.sql.SQLException; 4 5 public class DBUtil { 6 private static final String URL = "jdbc:mysql://127.0.0.1:3306/imooc"; 7 private static final String UNAME = "root"; 8 private static final String PWD = "root"; 9 10 private static Connection conn = null; 11 12 static { 13 try { 14 // 1.加載驅動程序 15 Class.forName("com.mysql.jdbc.Driver"); 16 // 2.得到數據庫的鏈接 17 conn = DriverManager.getConnection(URL, UNAME, PWD); 18 } catch (ClassNotFoundException e) { 19 e.printStackTrace(); 20 } catch (SQLException e) { 21 e.printStackTrace(); 22 } 23 } 24 25 public static Connection getConnection() { 26 return conn; 27 } 28 }
一種建立多餘對象的新方法,稱做自動裝箱(autoboxing),它容許程序員將基本類型和裝箱基本類型混用.
1 Integer sum = 0; 2 for(int i=1000; i<5000; i++){ 3 sum+=i; 4 }
對象包裝類是不變的,即一旦構造了包裝類,就不一樣意更改包裝在當中的值。同一時候,對象包裝類仍是final,所以不能定義它們的子類。
上面的代碼sum+=i可以當作sum = sum + i。但是+這個操做符不適用於Integer對象,首先sum進行本身主動拆箱操做。進行數值相加操做,最後發生本身主動裝箱操做轉換成Integer對象。其內部變化例如如下:
1 sum = sum.intValue() + i; 2 Integer sum = new Integer(result);
即使有垃圾回收功能也須要考慮內存管理的事情.
1 import java.util.Arrays; 2 import java.util.EmptyStackException; 3 4 public class Stack { 5 6 private Object[] elements; 7 private int size = 0; 8 private static final int DEFAULT_INITIAL_CAPACITY = 16; 9 10 public Stack() { 11 elements = new Object[DEFAULT_INITIAL_CAPACITY]; 12 } 13 14 private void ensureCapacity() { 15 if (elements.length == size) { 16 elements = Arrays.copyOf(elements, 2 * size + 1); 17 } 18 } 19 20 public void push(Object e) { 21 ensureCapacity(); 22 elements[size++] = e; 23 } 24 25 public Object pop() { 26 if (size == 0) { 27 throw new EmptyStackException(); 28 } 29 30 return elements[--size]; 31 } 32 33 }
1 public Object pop() { 2 if (size == 0) { 3 throw new EmptyStackException(); 4 } 5 6 Object result = elements[--size]; 7 elements[size] = null; // 清空引用 8 9 return result; 10 }
清空對象引用應該是一種例外,而不是一種規範行爲.消除過時引用最好的方法是讓包含該引用的變量結束其生命週期.
通常而言,只要類是本身管理內存,程序員就應該警戒內存泄漏問題.一旦元素被釋放掉,則該元素中包含的任何對象引用都應該被清空.
其餘內存泄漏常見來源:緩存,監聽器和其餘回調.
終結方法(finalizer)一般是不可預測的,也是很危險的,通常狀況下是沒必要要的.使用終結方法會致使行爲不穩定,下降性能,以及可移植性問題.
終結方法的缺點在於不能保證會被及時地執行.從一個對象變得不可能到達開始,到它的終結方法被執行,所花費的這段時間是任意長的.
說真的,我沒看懂,剩下的部分
不須要覆蓋:
應該覆蓋:
通用約定:
高質量equals的訣竅:
在每一個覆蓋了equals方法的類中,也必須覆蓋hashCode方法.若是不這樣作的話,就會違反Object.hashCode的通用約定,從而致使該類沒法結合全部基於散列的集合一塊兒正常運做,這樣的集合包括HashMap,HashSet和Hanshtable.
下面是約定的內容,摘自Object規範[JavaSE6]
爲不相等的對象產生不相等的散列碼.
簡單解決方法:
a.爲該域計算int類型的散列碼
i.若是該域是boolean類型,則計算(f ? 1 : 0)
ii:若是該域是byte,char,short或者int類型,則計算(int)f
iii:若是該域是long類型,則計算(int)( f ^ (f >>> 32) )
iv:若是該域是float類型,則計算Float.floatToIntBits(f)
v:若是該域是double類型,則計算Double.doubleToLongBits(f),而後按照步驟2.a.iii,爲獲得的long類型計算散列值
vi.若是該域是一個對象引用,而且該類的equlas方法通用遞歸調用equlas的方法來比較這個域,則一樣爲這個域遞歸地調用hashCode.若是須要更復炸的比較,則爲這個域計算一個範式,而後針對這個範式調用hashCode.若是這個域的值爲null,則返回0(或者其餘某個整數,但一般是0).
vii.若是該域是一個數組,則要把每個元素當作單獨的域來處理.也就是說,遞歸地應用上述規則,對每一個重要的元素計算一個散列碼,而後根據步驟2.b中的作法把這些散列值組合起來.若是數組域中的每一個元素都很重要,能夠利用發行版本1.5中增長的其中一個Arrays.hashCode方法.
b.按照下面的公式,把步驟2.a中計算獲得的散列碼c合併到result中:
result = 31 * result + c;
3.返回result
4.寫完hashCode方法以後,問問本身"相等的實例是否具備相等的散列碼".要編寫單元測試來驗證你的推斷.若是相等的實例有着不相等的散列碼,則要找出緣由,並修改錯誤.
在散列的計算過程當中,能夠把冗餘域排除在外.換句話說,若是一個域的值能夠根據參與計算的其餘域值計算出來,則能夠把這樣的域排除在外.
上述步驟1中用到一個非零的初始值,所以步驟2.a中計算的散列值爲0的那些初始域,會影響到散列值.若是步驟1中的初始值爲0,則整個散列值將不受這些初始域的影響,由於這些初始域會增長衝突的可能性
步驟2.b中的乘法部分使得散列值依賴於域的順序.若是一個類包含多個類似的域,這樣的乘法運算就會產生一個更好的散列函數.例如,若是String散列函數省略了這個乘法部分,那麼只是字母順序不一樣的全部字符串都會有相同的散列碼.
之因此選擇31,是由於它是一個奇數數.若是乘數是偶數,而且乘法溢出的話,信息就會丟失,由於與2相乘等價於移位運算.使用素數的好處並不明顯,但習慣上都是用素數來計算散列的結果.31有個很好的特性,即用移位和減法來代替乘法,能夠獲得更好的性能: 31 - i == ( i << 5 ) - i.現代的VM能夠自動完成這種優化.
關於31能夠看看這篇文章:https://segmentfault.com/a/1190000010799123
不要試圖從散列碼計算中排除掉一個對象的關鍵部分來提升性能.
雖然java.lang.Object提供了toString方法的一個實現,但它返回的字符串一般並非類的用戶所指望看到的.
它包含類的名稱,以及一個"@"符號,接着是散列碼的無符號十六進制表示法,例如"PhoneNumber@163b91".
toString的通用約定指出,被返回的字符串應該是一個"簡潔的,但信息豐富,而且易於閱讀的表達形式",
建議全部的子類都覆蓋這個方法.
當對象被傳遞給println,print,字符串聯操做符(+)以及assert或者被控制器打印出來時,toString方法會被自動調用.
toString方法應該返回對象中包含的全部值得關注的信息.
在實現toString的時候,必需要作出一個很重要的決定:是否在文檔中指定返回值的格式.
指定格式的好處是,它能夠被用一種標準的,明確的,適合人閱讀的對象表示法.若是你指定了格式,最好再提供一個相匹配的靜態工廠或者構造器,以便程序員能夠很容易地再對象和它的字符串表示法之間來回轉換.
指定格式的不足之處:若是這個類已經被普遍使用,一旦指定格式,就必須始終如一地堅持這種格式.若是不指定格式,就能夠保留靈活性,便於在未來的發行版本中增長信息,或則改進格式
我會將這些應用到之後的編程中,後期回來填坑補充本身的理解.