一、Integer 相等比較java
public static void main(String[] args) { Integer d =127; Integer f = 127; Integer e = 130; Integer g = 130; System.out.println(d==f);//true System.out.println(e==g);// false }
上述:總所周知,對象用==比較的話,是比較其地址,那麼上述爲什麼會出現2個結果呢?看源碼,發現當Integer的值不在-128~127之間的話,那麼就會從新new一個對象。故致使看到的結果。spring
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
二、繼承緩存
public class A { public void show(A obj){ System.out.println("A and A"); } public void show(B obj){ System.out.println("A and B"); } }
public class B extends A{ public void show(A obj){ System.out.println("B and A"); } public void show(C obj){ System.out.println("B and C"); } }
public class C extends B { }
public class D extends B { }
public static void main(String[] args) { A a = new A(); A a1 = new B(); B b = new B(); C c = new C(); D d = new D(); a.show(c); // A and B 先去A類中查找發現沒有該方法,可是C extends B 故結果A and B a.show(d);// A and B 同理上面 a.show(b);// A and B /** * 這裏雖然a1的類型是A 可是 實際引用的是B類 new B()會在堆區分配內存空間 *當a1.show(c)方法時,jvm會根據a1持有的引用定位到堆區的B實例 * 再根據B持有的引用 定位到方法區B類的類型(這時候是A)信息 得到show的字節, * 若是有重寫show方法的話,那麼就是調用B類中的show */ a1.show(c);// A and B a1.show(d);// A and B a1.show(a);// B and A 將優先和B類自己包含的實例方法動態綁定,若是沒有這個實例方法,纔會從父類A中繼承來的 }
三、單例安全
關於spring建立實例默認是單例模式,如想要配置成多例該怎麼辦呢?app
其實很簡單 在spring的配置文件中具體的bean配置scope=「prototype」這樣就是多例了。框架
<bean id="loginAction" class="com.business.common.action.LoginAction" scope="prototype"/>
關於單例的寫法有以下幾種實現方式jvm
/** *懶漢式 線程不安全 */ public class TestSingleton { private static TestSingleton testSingleton = null; private TestSingleton(){}; // 防止構建該實例 public static TestSingleton getSingleton(){ if(testSingleton == null){ testSingleton = new TestSingleton(); } return testSingleton; } }
/** * 餓漢式 天生就線程安全,類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了 */ public class TestSingleton { private static TestSingleton singleton = new TestSingleton(); private TestSingleton(){}; public static TestSingleton getIntance(){ return singleton; } }
public class TestSingleton { private static volatile TestSingleton singleton; private TestSingleton(){}; /** * 雙重校驗 線程安全 * @return */ public static TestSingleton getInstance(){ // 先判斷singleton該實例是否存在,若存在則直接返回,不存在的話建立。 if(null ==singleton){ // 若不寫上面的if判斷的話,那麼每次線程進來都須要發生鎖等待,避免了每次都同步的性能損耗 synchronized (TestSingleton.class){ if(null ==singleton){ singleton = new TestSingleton(); } } } return singleton; } }
那麼Spring對單例的底層實現,究竟是餓漢式單例仍是懶漢式單例呢?呵呵,都不是。Spring框架對單例的支持是採用單例註冊表的方式進行實現的,源碼以下:函數
public abstract class AbstractBeanFactory implements ConfigurableBeanFactory{ /** * 充當了Bean實例的緩存,實現方式和單例註冊表相同 */ private final Map singletonCache=new HashMap(); public Object getBean(String name)throws BeansException{ return getBean(name,null,null); } ... public Object getBean(String name,Class requiredType,Object[] args)throws BeansException{ //對傳入的Bean name稍作處理,防止傳入的Bean name名有非法字符(或則作轉碼) String beanName=transformedBeanName(name); Object bean=null; //手工檢測單例註冊表 Object sharedInstance=null; //使用了代碼鎖定同步塊,原理和同步方法類似,可是這種寫法效率更高 synchronized(this.singletonCache){ sharedInstance=this.singletonCache.get(beanName); } if(sharedInstance!=null){ ... //返回合適的緩存Bean實例 bean=getObjectForSharedInstance(name,sharedInstance); }else{ ... //取得Bean的定義 RootBeanDefinition mergedBeanDefinition=getMergedBeanDefinition(beanName,false); ... //根據Bean定義判斷,此判斷依據一般來自於組件配置文件的單例屬性開關 //<bean id="date" class="java.util.Date" scope="singleton"/> //若是是單例,作以下處理 if(mergedBeanDefinition.isSingleton()){ synchronized(this.singletonCache){ //再次檢測單例註冊表 sharedInstance=this.singletonCache.get(beanName); if(sharedInstance==null){ ... try { //真正建立Bean實例 sharedInstance=createBean(beanName,mergedBeanDefinition,args); //向單例註冊表註冊Bean實例 addSingleton(beanName,sharedInstance); }catch (Exception ex) { ... }finally{ ... } } } bean=getObjectForSharedInstance(name,sharedInstance); } //若是是非單例,即prototpye,每次都要新建立一個Bean實例 //<bean id="date" class="java.util.Date" scope="prototype"/> else{ bean=createBean(beanName,mergedBeanDefinition,args); } } ... return bean; } }
那麼spring在bean實例時是線程安全。性能
一種特殊化的單例模式,它被稱爲單例註冊表:ui
Import java.util.HashMap; Public class RegSingleton{ Static private HashMap registry=new HashMap(); //靜態塊,在類被加載時自動執行 Static{ RegSingleton rs=new RegSingleton(); Registry.put(rs.getClass().getName(),rs); } //受保護的默認構造函數,若是爲繼承關係,則能夠調用,克服了單例類不能爲繼承的缺點 Protected RegSingleton(){} //靜態工廠方法,返回此類的惟一實例 public static RegSingleton getInstance(String name){ if(name==null){ name=」 RegSingleton」; }if(registry.get(name)==null){ try{ registry.put(name,Class.forName(name).newInstance()); }Catch(Exception ex){ex.printStackTrace();} } Return (RegSingleton)registry.get(name); } }
四、JAXB bean to xml
須要生成以下對應的xml格式:
<T_TASK_APPROVE> <HEAD> <MSGCODE>T_TASK_APPROVE_</MSGCODE> <MSGID>T_TASK_APPROVE</MSGID> <MSGNAME>統一審批中心接收審批服務</MSGNAME> <SOURCESYS>hr</SOURCESYS> <TARGETSYS>HBTYSP</TARGETSYS> </HEAD> <DATA> <ROW> <PROPERTIES code="APP_ID">qq</PROPERTIES> <PROPERTIES code="service_ID">12345</PROPERTIES> </ROW> </DATA> </T_TASK_APPROVE>
一、首先建立最外層的結構
@XmlRootElement(name="T_TASK_APPROVE") public class BackLogData { private BackLogHeadData head; private BackLogPropertie data; @XmlElement(name="HEAD",nillable = true) public BackLogHeadData getHead() { return head; } public void setHead(BackLogHeadData head) { this.head = head; } @XmlElement(name="DATA") public BackLogPropertie getData() { return data; } public void setData(BackLogPropertie data) { this.data = data; } }
二、構建head中的數據
@XmlRootElement public class BackLogHeadData { private String msgcode; private String msgid; private String msgname; private String sourcesys; private String targetsys; private String createtime; @XmlElement(name="MSGCODE",nillable = true) public String getMsgcode() { return this.msgcode; } public void setMsgcode(String msgcode) { this.msgcode = msgcode; } @XmlElement(name="MSGID",nillable = true) public String getMsgid() { return this.msgid; } public void setMsgid(String msgid) { this.msgid = msgid; } @XmlElement(name="MSGNAME",nillable = true) public String getMsgname() { return this.msgname; } public void setMsgname(String msgname) { this.msgname = msgname; } @XmlElement(name="SOURCESYS",nillable = true) public String getSourcesys() { return this.sourcesys; } public void setSourcesys(String sourcesys) { this.sourcesys = sourcesys; } @XmlElement(name="TARGETSYS",nillable = true) public String getTargetsys() { return this.targetsys; } public void setTargetsys(String targetsys) { this.targetsys = targetsys; } @XmlElement(name="CREATETIME",nillable = true) public String getCreatetime() { return this.createtime; } public void setCreatetime(String createtime) { this.createtime = createtime; } }
三、構造DATA節點中的數據
@XmlRootElement public class BackLogPropertie { private List<Propertie> properties; @XmlElementWrapper(name="ROW") @XmlElement(name="PROPERTIES") public List<Propertie> getProperties() { return properties; } public void setProperties(List<Propertie> properties) { this.properties = properties; } }
生成xml代碼
public static void main(String args[]) { BackLogData backLogData = new BackLogData(); BackLogHeadData head = new BackLogHeadData(); head.setMsgcode("T_TASK_APPROVE_"); head.setMsgid("T_TASK_APPROVE"); head.setMsgname("統一審批中心接收審批服務"); head.setSourcesys("hr"); head.setTargetsys("HBTYSP"); BackLogPropertie backLogPropertie = new BackLogPropertie(); List<Propertie> properties = new ArrayList<>(); Propertie appId = new Propertie(); appId.setCode("APP_ID"); appId.setValue("qq"); properties.add(appId); Propertie serviceId = new Propertie(); serviceId.setCode("service_ID"); serviceId.setValue("12345"); properties.add(serviceId); backLogPropertie.setProperties(properties); backLogData.setHead(head); backLogData.setData(backLogPropertie); String xmlData = XmlBuilder.convertToXml(backLogData); System.out.println(xmlData); }