其余:首先感谢知了堂-阳哥在学习道路上长达一年的陪伴,也很庆幸在知了堂碰见鑫鑫.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的时候,必需要作出一个很重要的决定:是否在文档中指定返回值的格式.
指定格式的好处是,它能够被用一种标准的,明确的,适合人阅读的对象表示法.若是你指定了格式,最好再提供一个相匹配的静态工厂或者构造器,以便程序员能够很容易地再对象和它的字符串表示法之间来回转换.
指定格式的不足之处:若是这个类已经被普遍使用,一旦指定格式,就必须始终如一地坚持这种格式.若是不指定格式,就能够保留灵活性,便于在未来的发行版本中增长信息,或则改进格式
我会将这些应用到之后的编程中,后期回来填坑补充本身的理解.