1、Java的反射机制:
(1)通过 类名称.class,对基本类型也支持;
Class c = int.class;
Class c = int[ ].class;
Class c = String.class
(2)通过 对象.getClass( )方法
Class c = obj.getClass( );
(3) Class.forName( ) 通过类名称加载类,这种方法只要有类名称就可以得到Class;
Class c = Class.forName(“cn.ywq.Demo”);
示例:通过反射来创建一个对象,利用.newInstance( )方法来实现。
public class Demo1 { @Test public void fun1() throws Exception { String className = "cn.ywq.User"; Class clazz = Class.forName(className); User user = (User)clazz.newInstance(); System.out.println(user); } } class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [username=" + username + ", password=" + password + "]"; } }
5、Field类的使用
Field表示类的成员变量,可以是实例变量,也可以是静态变量。
(1)获取Field对象,
获取Field对象需要使用Class对象,下面是Class类的API:
Field getField(String name):通过名字获取公有成员变量的反射对象,包含父类中声明的公有成员变量;
Field[ ] getFields():获取所有公有成员变量反射对象,包含父类中声明的公有成员变量;
Field getDeclaredField(String name):通过名字获取本类中某个成员变量,包含本类的private成员变量,但父类中声明的任何成员变量都不包含;
Field[ ] getDeclaredFields():获取本类中声明的所有成员变量,包含private成员变量,但不包含父类中声明的任何成员变量;
(2)Field类的常用方法
String getName():获取成员变量名;
Class getDeclaringClass():获取成员变量的类型;
Class getType():获取当前成员变量的类型;
Object get(Object obj):获取obj对象的成员变量的值;
void set(Object obj, Object value):设置obj对象的成员变量值为value;
示例:通过Field读写成员
User.java
public class User { public String username; public String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [username=" + username + ", password=" + password + "]"; } }
Demo1.java
public class Demo1 { @Test public void fun1() throws Exception { String className = "cn.itcast.User"; Class clazz = Class.forName(className); User user = new User("zhangSan", "123"); Field field1 = clazz.getField("username"); Field field2 = clazz.getField("password") ; String username = (String)field1.get(user); String password = (String)field2.get(user); System.out.println(username + ", " + password); field1.set(user, "liSi"); field2.set(user, "456"); System.out.println(user); } }
Constructor表示一个类的构造器。即构造器的反射对象!
(1)获取Constructor对象
获取Construcator对象需要使用Class对象,下面API来自Class类:
Constructor getConstructor(Class… parameterTypes):通过指定的参数类型获取公有构造器反射对象;
Constructor[ ] getConstructors( ):获取所有公有构造器对象;
Constructor getDeclaredConstructor(Class… parameterTypes):通过指定参数类型获取构造器反射对象。可以是私有构造器对象;
Constructor[ ] getDeclaredConstructors():获取所有构造器对象。包含私有构造器;
(2)Construcator类常用方法
String getName():获取构造器名;
Class getDeclaringClass():获取构造器所属的类型;
Class[ ] getParameterTypes():获取构造器的所有参数的类型;
Class[ ] getExceptionTypes():获取构造器上声明的所有异常类型;
newInstance(Object… initargs):通过构造器反射对象调用构造器。
示例:通过Construcator创建对象
User.java
public class User { private String username; private String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [username=" + username + ", password=" + password + "]"; } }
Demo1.java
public class Demo1 { @Test public void fun1() throws Exception { String className = "cn.itcast.User"; Class clazz = Class.forName(className); Constructor c = clazz.getConstructor(String.class, String.class); User user = (User)c.newInstance("zhangSan", "123"); System.out.println(user); } }
(1)获取Method
获取Method需要通过Class对象,下面是Class类的API:
Method getMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取方法反射对象,包含父类中声明的公有方法,但不包含所有私有方法;
Method[ ] getMethods():获取所有公有方法,包含父类中的公有方法,但不包含任何私有方法;
Method getDeclaredMethod(String name, Class… parameterTypes):通过方法名和方法参数类型获取本类中声明的方法的反射对象,包含本类中的私有方法,但不包含父类中的任何方法;
Method[ ] getDeclaredMethods( ):获取本类中所有方法,包含本类中的私有方法,但不包含父类中的任何方法。
(2)Method常用方法
String getName( ):获取方法名;
Class getDeclaringClass( ):获取方法所属的类型;
Class[ ] getParameterTypes( ):获取方法的所有参数的类型;
Class[ ] getExceptionTypes( ):获取方法上声明的所有异常类型;
Class getReturnType( ):获取方法的返回值类型;
Object invode(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数;
示例:通过Method调用方法
public class Demo1 { @Test public void fun1() throws Exception { String className = "cn.ywq.User"; Class clazz = Class.forName(className); Constructor c = clazz.getConstructor(String.class, String.class); User user = (User)c.newInstance("zhangSan", "123"); Method method = clazz.getMethod("toString"); String result = (String)method.invoke(user); System.out.println(result); } }
AccessibleObject类是Constructor、Method、Field三个类的父类。AccessibleObject最为重要的方法如下:
boolean isAccessible( ):判断当前成员是否可访问;
voidsetAccessible(boolean flag):设置当前成员是否可访问。
当Constructor、Method、Field为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。
User.java
public class User { private String username; private String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [username=" + username + ", password=" + password + "]"; } }
注意,User类的username和password成员变量为private的,这时再通过Field来反射操作这两个成员变量就必须先通过setAccessible(true)设置后才行。
public class Demo1 { @Test public void fun1() throws Exception { String className = "cn.ywq.User"; Class clazz = Class.forName(className); User user = new User("zhangSan", "123"); Field field1 = clazz.getDeclaredField("username"); Field field2 = clazz.getDeclaredField("password"); field1.setAccessible(true); field2.setAccessible(true); String username = (String)field1.get(user); String password = (String)field2.get(user); System.out.println(username + ", " + password); field1.set(user, "liSi"); field2.set(user, "456"); System.out.println(user); } }
9、Java反射机制在工厂方法模式中的使用:
工厂方法模式模式主要的作用就是创建一个对象,它是new一个对象的替代品。在所有需要生成对象的地方都可以使用。
工厂方法模式利用Java的反射机制来得到Class类,利用newInstance( )方法来创建一个对象。
通用类图如下所示:
通用源代码:
//抽象产品类 public abstract class Product { //产品类的公共方法 public void method1(){ //业务逻辑处理 } //抽象方法 public abstract void method2(); } //多个具体产品类 public class ConcreteProduct1 extends Product { public void method2() { //业务逻辑处理 } } public class ConcreteProduct2 extends Product { public void method2() { //业务逻辑处理 } } //抽象工厂类 public abstract class Creator { /* * 创建一个产品对象,其输入参数类型可以自行设置 * 通常为String、Enum、Class等,当然也可以为空 */ public abstract <T extends Product> T create Product(Class<T> c); } //具体工厂类 public class ConcreteCreator extends Creator { public <T extends Product> T create Product(Class<T> c){ Product product=null; try { product = (Product)Class.forName(c.get Name()).new Instance(); } catch (Exception e) { //异常处理 } return (T)product; } }
测试代码如下:
public class Client { public static void main(String[] args) { Creator creator = new ConcreteCreator(); Product product = creator.createProduct(ConcreteProduct1.class); /* * 继续业务处理 */ } }
可以看到,工厂方法模式中,在具体的工厂中使用了反射机制来创建了一个product的对象。