1.静态代码块和非静态代码块以及构造函数
出自尚学堂视频:《JVM核心机制 类加载全过程 JVM内存分析 反射机制核心原理 常量池理解》
public class Parent {
static String name = "hello";
//非静态代码块
{
System.out.println("1");
}
//静态代码块
static {
System.out.println("2");
}
public Parent() {
System.out.println("3");
}
}
public class Child extends Parent {
static String childName = "hello";
{
System.out.println("4");
}
static {
System.out.println("5");
}
public Child() {
System.out.println("6");
}
}
调用测试
public class StaticCodeBlockOrderTest {
public static void main(String[] args) {
new Child();
}
}
对象的初始化顺序:
首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,
如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。
子类的非静态代码块执行完毕再去执行子类的构造方法。
参考:java中静态代码块的用法 static用法详解
静态代码块的应用
需要一个Util类,需要系统初始化的时候就初始化一个hashMap,部分代码省略以...代替
private static Map> smap = new HashMap>();
static {
for (int i = 0; i < k; i++) {
List ls = new ArrayList();
ls.add(...);
ls.add(...);
smap.put(..., ls);
}
}
这个一样的用法:Map的静态赋值
-------------------
这个老外讲的很好《Java Generics》
泛型方法
static 后的
static
泛型类:
不用泛型需要强转:
2.泛型 Class
public class Box {
private T t;
public Box(){
}
public Box(T data){
this.t=data;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
调用
public static void main(String[] args) {
Box s=new Box("abc");
Box i=new Box(123);
System.out.println("s class:" + s.getClass());
System.out.println("i class:" + i.getClass());
System.out.println(s.getClass() == i.getClass());
}
输出
为什么有Class
其实看这个就明白了
在其他类中例如这个Test里,你可以定义
public static void getData(Box data){
System.out.println("data :" + data.getT());
}
也可以定义
public static void getData(Box data){
System.out.println("data :" + data.getT());
}
但是你要是同时定义这2个就会报错
名称冲突: getData(Box
使用通配符?就可以解决这个问题
public class TestMain {
public static void main(String[] args) {
Box s=new Box("abc");
Box i=new Box(123);
System.out.println("s class:" + s.getClass());
System.out.println("i class:" + i.getClass());
System.out.println(s.getClass() == i.getClass());
getData(s);
getData(i);
}
public static void getData(Box> data){
System.out.println("data :" + data.getT());
}
}
参考:
Java总结篇系列:Java泛型
java中的泛型总结
再来看看Class>的用处
public class TestMain {
public static void main(String[] args) {
Box s=new Box("http://blog.csdn.net/unix21");
Box i=new Box(123);
System.out.println("s class:" + s.getClass());
System.out.println("i class:" + i.getClass());
System.out.println(s.getClass() == i.getClass());
getData(Box.class);
}
public static void getData(Class> clz){
try {
System.out.println(clz);
System.out.println("clz.hashCode():" + clz.hashCode());
Object o=clz.newInstance();
o.hashCode();
System.out.println("o.hashCode():" + o.hashCode());
}
catch (Exception e) {
System.out.println(e);
}
}
}
((Box)clz).getT();会报错:
不能将 "class java.lang.Class (no class loader)" 的实例强制转换为 "class test.Box (loaded by instance of sun.misc.Launcher$AppClassLoader(id=144))" 的实例
说明还没有class loader
((Box)o).getT();就已经实例化了。
3.Object类型
定义的所有类默认都是子类,所有的类都是以标准类Object为基础,Object类型的变量可以存储指向任意类类型对象的索引。
当要为一个方法来处理未知类型的对象时,这很有用。
//存储的地方
HashMap map = new HashMap();
User u1=new User();
u1.setId(1);
u1.setName("ww1");
//Object可以塞任意类型
map.put("user",u1);
User u=(User)map.get("user");
response.getWriter().println("Hello Servlet >>>"+u.getName());
String clazz ="com.w1.User"; //bean.getAttributeValue("class");
try {
//反射
Object o = Class.forName(clazz).newInstance();
map.put("user2",o);
User u2=(User)map.get("user2");
u2.setName("ww223");
response.getWriter().println("Hello Servlet >>>"+u2.getName());
} catch (Exception e) {
e.printStackTrace();
}
4.类名.class, class.forName(), getClass()区别
1:Class cl=A.class;
JVM将使用类A的类装载器, 将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象。
2:Class cl=对象引用o.getClass();
返回引用o运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象 。
3:Class.forName("类名");
.装入类A,并做类的初始化
.getClass()是动态的,其余是静态的。
.class和class.forName()只能返回类内field的默认值,getClass可以返回当前对象中field的最新值
Class.forName() 返回的是一个类,.newInstance() 后才创建一个对象,Class.forName()的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的。
public class Person {
private String name = "Alfira";
public void getName() {
System.out.println(name);
}
public void setName(String name, int a) {
this.name = name + a;
}
}
private static void show(String name) {
try {
// JVM将使用类A的类装载器,将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作
Class classtype3 = Person.class;
// 获得classtype中的方法
Method getMethod3 = classtype3.getMethod("getName", new Class[] {});
Class[] parameterTypes3 = { String.class, int.class };
Method setMethod3 = classtype3.getMethod("setName", parameterTypes3);
// 实例化对象,因为这一句才会输出“静态初始化”以及“初始化”
Object obj3 = classtype3.newInstance();
// 通过实例化后的对象调用方法
getMethod3.invoke(obj3); // 获取默认值
setMethod3.invoke(obj3, "Setting new ", 3); // 设置
getMethod3.invoke(obj3); // 获取最新
System.out.println("----------------");
// 返回运行时真正所指的对象
Person p = new Person();
Class classtype = p.getClass();// Class.forName(name);
// 获得classtype中的方法
Method getMethod = classtype.getMethod("getName", new Class[] {});
Class[] parameterTypes = { String.class, int.class };
Method setMethod = classtype.getMethod("setName", parameterTypes);
getMethod.invoke(p);// 获取默认值
setMethod.invoke(p, "Setting new ", 1); // 设置
getMethod.invoke(p);// 获取最新
System.out.println("----------------");
// 装入类,并做类的初始化
Class classtype2 = Class.forName(name);
// 获得classtype中的方法
Method getMethod2 = classtype2.getMethod("getName", new Class[] {});
Class[] parameterTypes2 = { String.class, int.class };
Method setMethod2 = classtype2.getMethod("setName", parameterTypes2);
// 实例化对象
Object obj2 = classtype2.newInstance();
// 通过实例化后的对象调用方法
getMethod2.invoke(obj2); // 获取默认值
setMethod2.invoke(obj2, "Setting new ", 2); // 设置
getMethod2.invoke(obj2); // 获取最新
System.out.println("----------------");
} catch (Exception e) {
System.out.println(e);
}
}
调用
show("com.Person");
参考此文:http://www.cnblogs.com/feiyun126/archive/2013/08/01/3229492.html
http://blog.163.com/granite8@126/blog/static/853746082008610102657141/
5.动态代理和cglib
public class SayHello {
public void say(){
System.out.println("hello everyone");
}
}
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz) {
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
return enhancer.create();
}
//实现MethodInterceptor接口方法
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置代理");
return result;
}
}
调用
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
SayHello proxyImp = (SayHello)proxy.getProxy(SayHello.class);
proxyImp.say();
CGLib动态代理原理及实现
Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)[转]
cglib动态代理介绍(一)
6.模仿Spring实现
需要说这个作者写到这一系列文章非常好【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)
代码:http://download.csdn.net/detail/jiuqiyuliang/8483981
这篇博文的目标是不仅形似Spring的IoC,而且要神似Spring的IoC,将对象的依赖关系进一步封装。
完整的项目结构
Dao接口和实现
public interface Dao {
public void daoMethod();
}
public class Dao4MySqlImpl implements Dao {
public void daoMethod(){
System.out.println("Dao4MySqlImpl.daoMethod()");
}
}
public class Dao4OracleImpl implements Dao {
public void daoMethod(){
System.out.println("Dao4OracleImpl.daoMethod()");
}
}
Service接口和实现
public interface Service {
public void serviceMethod();
}
public class ServiceImpl implements Service {
private Dao dao;
//依赖注入
public void setDao(Dao dao) {
this.dao= dao;
}
@Override
public void serviceMethod() {
dao.daoMethod();
}
}
public interface BeanFactory {
Object getBean(String beanName);
}
import java.util.ArrayList;
import java.util.List;
public class BeanDefinition {
private String id;
private String className;
private List propertys = new ArrayList();
public BeanDefinition(String id, String className) {
this.id = id;
this.className = className;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List getPropertys() {
return propertys;
}
public void setPropertys(List propertys) {
this.propertys = propertys;
}
}
核心容器
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 容器
*
* @author liang
*
*/
public class ClassPathXmlApplicationContext implements BeanFactory {
// 用于存放Bean
private List beanDefines = new ArrayList();
// 用于存放Bean的实例
private Map sigletons =new HashMap();
public ClassPathXmlApplicationContext(String fileName) {
this.readXML(fileName);
this.instanceBeans();
this.injectObject();
}
/**
* 为bean对象的属性注入值
*/
private void injectObject() {
for (BeanDefinition beanDefinition :beanDefines) {
Object bean = sigletons.get(beanDefinition.getId());
if(bean != null){
try {
// 通过Introspector取得bean的定义信息,之后再取得属性的描述信息,返回一个数组
PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){
for(PropertyDescriptor properdesc: ps){
if(propertyDefinition.getName().equals(properdesc.getName())){
// 获取属性的setter方法,private
Method setter = properdesc.getWriteMethod();
if(setter != null){
Object value = sigletons.get(propertyDefinition.getRef());
// 允许访问私有方法
setter.setAccessible(true);
// 把引用对象注入到属性
setter.invoke(bean, value);
}
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 完成bean的实例化
*/
private void instanceBeans() {
for(BeanDefinition beanDefinition : beanDefines){
try {
if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){
sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 读取xml配置文件
*/
private void readXML(String fileName) {
// 创建SAXBuilder对象
SAXBuilder saxBuilder = new SAXBuilder();
try {
// 读取资源,获得document对象
Document doc = saxBuilder.build(this.getClass().getClassLoader()
.getResourceAsStream(fileName));
// 获取根元素
Element rootEle = doc.getRootElement();
// 从根元素获得所有的子元素,建立元素集合
List listBean = XPath.selectNodes(rootEle, "/beans/bean");
// 遍历根元素的子元素集合,扫描配置文件中的bean
for (int i = 0; i < listBean.size(); i++) {
// 将根元素beans下的bean子元素作为一个新的子根元素
Element elementBean = (Element) listBean.get(i);
//获取id属性值
String id = elementBean.getAttributeValue("id");
//获取class属性值
String clazz = elementBean.getAttributeValue("class");
BeanDefinition beanDefine = new BeanDefinition(id,clazz);
// 获取子根元素bean下的所有property子元素
List listProperty = elementBean.getChildren("property");
// 遍历子根元素的子元素集合(即遍历property元素)
for (int j = 0; j < listProperty.size(); j++) {
// 获取property元素
Element elmentProperty = (Element)listProperty.get(j);
// 获取name属性值
String propertyName = elmentProperty.getAttributeValue("name");
// 获取ref属性值
String propertyref = elmentProperty.getAttributeValue("ref");
PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName,propertyref);
beanDefine.getPropertys().add(propertyDefinition);
}
// 将javabean添加到集合中
beanDefines.add(beanDefine);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取bean实例
*/
@Override
public Object getBean(String beanName) {
return this.sigletons.get(beanName);
}
}
public class PropertyDefinition {
private String name;
private String ref;
public PropertyDefinition(String name, String ref) {
this.name = name;
this.ref = ref;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}
applicationContext.xml
7.Smart Framework
Smart Framework:轻量级 Java Web 框架
Smart Framework是一个完整的类似Spring但是更轻量级的项目,学习框架的最佳材料之一。