三种实例化对象:
1、Class<?> cls = Class.forName("java.util.Date") ; *** System.out.println(cls.getName()); 2、类.class 3、对象.getClass
Class<?> cls = Class.forName("java.util.Date") ; Object obj = cls.newInstance() ; // 实例化对象,等价于 new java.util.Date() 等价于 Date date = new Date()
class Main{ public static void main(String[] args) { System.out.println(new java.util.Date()==new java.util.Date()); //false } }
获得包名: Class<?> cls = CLS.class ; // 取得Class类对象 System.out.println(cls.getPackage().getName()); 获得父类接口: Class<?> cls = CLS.class ; // 取得Class类对象 System.out.println(cls.getSuperclass().getName()); // 取得实现的父接口对象 Class<?>[] iClass = cls.getInterfaces() ; for (Class<?> class1 : iClass) { System.out.println(class1.getName()); } 获得构造方法: Class<?> cls = Person.class ; // 取得类中的全部构造 Constructor<?>[] constructors = cls.getConstructors() ; for (Constructor<?> constructor : constructors) { System.out.println(constructor); } 获取指定参数的构造: public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException 在定义简单java类的时候一定要保留有一个无参构造 Class类通过反射实例化类对象的时候,只能够调用类中的无参构造。如果现在类中没有无参构造则无法使用Class 类调用,只能够通过明确的构造调用实例化处理。
反射获得Date构造方法:
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.text.SimpleDateFormat; class Main{ public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class<?> cls = Class.forName("java.text.SimpleDateFormat"); Constructor<?>[] constructor = cls.getConstructors(); for (Constructor<?> constructor1 : constructor){ System.out.println(constructor1); } // SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // String str = simpleDateFormat.format(new Date()); // System.out.println(str); Constructor<?> cons = cls.getConstructor(String.class); System.out.println((SimpleDateFormat)cons.newInstance("yyyy-MM-dd HH:mm:ss")); } }
反射获得指定参数构造方法
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; class Person { private String name ; private int age ; public Person(String name,int age) { this.name = name ; this.age = age ; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } } class Test { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { Class<?> cls = Person.class; // 取得指定参数类型的构造方法对象 Constructor<?> cons = cls.getConstructor(String.class, int.class); System.out.println(cons.newInstance("yuisama", 29)); } }
public Method[] getMethods() throws SecurityException public Method getMethod(String name, Class<?>... parameterTypes) public static void main(String[] args) throws Exception { Class<?> cls = Person.class ; Method[] methods = cls.getMethods() ; for (Method method : methods) { System.out.println(method); } }
import java.lang.reflect.Method; class Person { private String name ; private int age ; public Person() {} public Person(String name,int age) { this.name = name ; this.age = age ; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class Test { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("www.java.hhy.Person") ; // 任何时候调用类中的普通方法都必须有实例化对象 Object obj = cls.newInstance() ; // 取得setName这个方法的实例化对象,设置方法名称与参数类型 Method setMethod = cls.getMethod("setName", String.class) ; // 随后需要通过Method类对象调用指定的方法,调用方法需要有实例化对象 // 同时传入参数 setMethod.invoke(obj, "yuisama") ; // 相当于Person对象.setName("yuisama") ; Method getMethod = cls.getMethod("getName") ; Object result = getMethod.invoke(obj) ; // 相当于Person对象.getName() ; System.out.println(result) ; }
}
此类操作的好处是:不再局限于某一具体类型的对象,而是可以通过Object类型进行所有类的方法调用
--------------------------------------------------------- 属性的获取 public class Test { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("www.bit.java.testthread.Student") ; { // 普通代码 // 第一组-取得父类中全部属性 Field[] fields = cls.getFields() ; for (Field field : fields) { System.out.println(field) ; } } System.out.println("------------------------"); { // 第二组-取得类中全部属性 Field[] fields = cls.getDeclaredFields() ; for (Field field : fields) { System.out.println(field); } } } }
package www.bit.java.testthread; import java.lang.reflect.Field; class Person { private String name ; } public class Test { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("www.bit.java.testthread.Person") ; // 实例化本类对象 Object obj = cls.newInstance() ; // 操作name属性 Field nameField = cls.getDeclaredField("name") ; nameField.set(obj, "yuisama") ; // 相当于对象.name = "yuisama" System.out.println(nameField.get(obj)); // 取得属性 } }
自定义类加载器
cls.getClassLoader() = AppClassLoader(应用程序类加载器)
cls.getClassLoader().getParent()) = ExtClassLoader(扩展类加载器);
最顶层: Bootstrap(启动类加载器): 启动类加载器无法被Java程序直接引用。
-------------------------------------------------------------------
双亲委派模型:
我们的应用程序都是由这三种加载器互相配合进行加载的,如果有必要,还可以加入自定义的类加载器。
双亲委派模型要求除了顶层的父类加
载器外,其余的类加载器都应有自己的父类加载器。
双亲委派模型的工作流程是:如果一个类加载器收到了类加载请求,它首先不会自己去尝试加载这个类,而是把这
个请求委托给父类加载器去完成,每一个层次的类加载器都是如此。因此,所有的加载请求都应当传送到顶层的
BootStrap加载器中,只有当父加载器反馈无法完成这个加载请求时(在自己搜索范围中没有找到此类),子加载器
才会尝试自己去加载。
类加载器的双亲委派模型从JDK1.2引入后被广泛应用于之后几乎所有的Java程序中,但它并不是强制性约束,甚至
可以破坏双亲委派模型来进行类加载,最典型的就是OSGI技术。
双亲委派模式对于保证Java程序的稳定运行很重要。有一个显而易见的好处就是Java类随着它的类加载器一起具备
了一种带有优先级的层次关系。例如java.lang.Object类,它存放在rt.jar中,无论哪一个类加载器要加载这个类,
最终都是委派给处于顶端的启动类加载器进行加载。因此,Object类在程序的各种类加载器环境中都是同一个类
比较两个类相等的前提:必须是由同一个类加载器加载的前提下才有意义。否则,即使两个类来源于同一个Class
文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那么这两个类注定不想等。
动态代理模式
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; interface ISubject { // 核心操作接口 public void eat(String msg, int num) ; // 吃饭是核心业务 } class RealSubject implements ISubject { @Override public void eat(String msg ,int num) { System.out.println("我要吃 "+num + "分量的 "+msg) ; } } /** * 动态代理类 */ class ProxySubject implements InvocationHandler { // 绑定任意接口的对象,使用Object描述 private Object target ; /** * 实现真实对象的绑定处理,同时返回代理对象 * @param target * @return 返回一个代理对象(这个对象是根据接口定义动态创建生成的代理对象) */ public Object bind(Object target) { // 保存真实主题对象 this.target = target ; return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfac es(),this) ; } public void preHandle() { System.out.println("[ProxySubject] 方法处理前") ; } public void afterHandle(){ System.out.println("[ProxySubject] 方法处理后") ; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { this.preHandle() ; // 反射调用方法 Object ret = method.invoke(this.target,args) ; this.afterHandle() ; return ret; } } public class TestDemo { public static void main(String[] args) { ISubject subject =(ISubject) new ProxySubject().bind(new RealSubject()) ; subject.eat("宫保鸡丁",20) ; } }