一、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); }