摘要:本文将带你了解Java语言之反射机制,希望本文对大家学JAVA有所帮助。
Java反射机制(带应用)
1、Java的反射机制:
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
但是Java有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
************************************************************************************************************************
以上是百度百科中对Java反射机制的解释。
2、Java反射机制的功能:
(1)在运行时判断任意一个对象所属的类;
(2)在运行时构造任意一个类的对象;
(3)在运行时判断任意一个类所具有的成员变量和方法;
(4)在运行时调用任意一个对象的方法;生成动态代理。
3、与反射相关的类有:
Class:表示类、Field:表示成员变量、 Method:表示方法、Constructor:表示构造器。
4、获取Class类的三种基本方式:
(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( )方法来实现。
[java] view plain copy 1. public class Demo1 { 2. @Test 3. public void fun1() throws Exception { 4. String className = "cn.ywq.User"; 5. Class clazz = Class.forName(className); 6. User user = (User)clazz.newInstance(); 7. System.out.println(user); 8. } 9. } 10. 11. class User { 12. private String username; 13. private String password; 14. 15. public String getUsername() { 16. return username; 17. } 18. 19. public void setUsername(String username) { 20. this.username = username; 21. } 22. 23. public String getPassword() { 24. return password; 25. } 26. 27. public void setPassword(String password) { 28. this.password = password; 29. } 30. 31. @Override 32. public String toString() { 33. return "User [username=" + username + ", password=" + password + "]"; 34. } 35. } 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 [java] view plain copy 1. public class User { 2. public String username; 3. public String password; 4. 5. public User() { 6. } 7. 8. public User(String username, String password) { 9. this.username = username; 10. this.password = password; 11. } 12. 13. public String getUsername() { 14. return username; 15. } 16. 17. public void setUsername(String username) { 18. this.username = username; 19. } 20. 21. public String getPassword() { 22. return password; 23. } 24. 25. public void setPassword(String password) { 26. this.password = password; 27. } 28. 29. @Override 30. public String toString() { 31. return "User [username=" + username + ", password=" + password + "]"; 32. } 33. } Demo1.java [java] view plain copy 1. public class Demo1 { 2. @Test 3. public void fun1() throws Exception { 4. String className = "cn.itcast.User"; 5. Class clazz = Class.forName(className); 6. User user = new User("zhangSan", "123"); 7. 8. Field field1 = clazz.getField("username"); 9. Field field2 = clazz.getField("password") ; 10. 11. String username = (String)field1.get(user); 12. String password = (String)field2.get(user); 13. 14. System.out.println(username + ", " + password); 15. 16. field1.set(user, "liSi"); 17. field2.set(user, "456"); 18. 19. System.out.println(user); 20. } 21. } 6、Constructor类的使用 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 [java] view plain copy 1. public class User { 2. private String username; 3. private String password; 4. 5. public User() { 6. } 7. 8. public User(String username, String password) { 9. this.username = username; 10. this.password = password; 11. } 12. 13. public String getUsername() { 14. return username; 15. } 16. 17. public void setUsername(String username) { 18. this.username = username; 19. } 20. 21. public String getPassword() { 22. return password; 23. } 24. 25. public void setPassword(String password) { 26. this.password = password; 27. } 28. 29. @Override 30. public String toString() { 31. return "User [username=" + username + ", password=" + password + "]"; 32. } 33. } Demo1.java [java] view plain copy 1. public class Demo1 { 2. @Test 3. public void fun1() throws Exception { 4. String className = "cn.itcast.User"; 5. Class clazz = Class.forName(className); 6. Constructor c = clazz.getConstructor(String.class, String.class); 7. User user = (User)c.newInstance("zhangSan", "123"); 8. System.out.println(user); 9. } 10. } 7、Method类的使用 (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 invoke(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数; 示例:通过Method调用方法 [java] view plain copy 1. public class Demo1 { 2. @Test 3. public void fun1() throws Exception { 4. String className = "cn.ywq.User"; 5. Class clazz = Class.forName(className); 6. Constructor c = clazz.getConstructor(String.class, String.class); 7. User user = (User)c.newInstance("zhangSan", "123"); 8. 9. Method method = clazz.getMethod("toString"); 10. String result = (String)method.invoke(user); 11. System.out.println(result); 12. } 13. }
8、AccessibleObject的使用
AccessibleObject类是Constructor、Method、Field三个类的父类。AccessibleObject最为重要的方法如下:
boolean isAccessible( ):判断当前成员是否可访问;
voidsetAccessible(boolean flag):设置当前成员是否可访问。
当Constructor、Method、Field为私有时,如果我们想反射操作,那么就必须先调用反射对象的setAccessible(true)方法,然后才能操作。
User.java
[java] view plain copy 1. public class User { 2. private String username; 3. private String password; 4. 5. public User() { 6. } 7. 8. public User(String username, String password) { 9. this.username = username; 10. this.password = password; 11. } 12. 13. public String getUsername() { 14. return username; 15. } 16. 17. public void setUsername(String username) { 18. this.username = username; 19. } 20. 21. public String getPassword() { 22. return password; 23. } 24. 25. public void setPassword(String password) { 26. this.password = password; 27. } 28. 29. @Override 30. public String toString() { 31. return "User [username=" + username + ", password=" + password + "]"; 32. } 33. } 注意,User类的username和password成员变量为private的,这时再通过Field来反射操作这两个成员变量就必须先通过setAccessible(true)设置后才行。 [java] view plain copy 1. public class Demo1 { 2. @Test 3. public void fun1() throws Exception { 4. String className = "cn.ywq.User"; 5. Class clazz = Class.forName(className); 6. User user = new User("zhangSan", "123"); 7. 8. Field field1 = clazz.getDeclaredField("username"); 9. Field field2 = clazz.getDeclaredField("password"); 10. 11. field1.setAccessible(true); 12. field2.setAccessible(true); 13. 14. String username = (String)field1.get(user); 15. String password = (String)field2.get(user); 16. 17. System.out.println(username + ", " + password); 18. 19. field1.set(user, "liSi"); 20. field2.set(user, "456"); 21. 22. System.out.println(user); 23. } 24. }
9、Java反射机制在工厂方法模式中的使用:
工厂方法模式模式主要的作用就是创建一个对象,它是new一个对象的替代品。在所有需要生成对象的地方都可以使用。
工厂方法模式利用Java的反射机制来得到Class类,利用newInstance( )方法来创建一个对象。
通用类图如下所示:
通用源代码:
[java] view plain copy 1. //抽象产品类 2. public abstract class Product { 3. //产品类的公共方法 4. public void method1(){ 5. //业务逻辑处理 6. } 7. //抽象方法 8. public abstract void method2(); 9. } 10. 11. //多个具体产品类 12. public class ConcreteProduct1 extends Product { 13. public void method2() { 14. //业务逻辑处理 15. } 16. } 17. public class ConcreteProduct2 extends Product { 18. public void method2() { 19. //业务逻辑处理 20. } 21. } 22. 23. //抽象工厂类 24. public abstract class Creator { 25. /* 26. * 创建一个产品对象,其输入参数类型可以自行设置 27. * 通常为String、Enum、Class等,当然也可以为空 28. */ 29. public abstract <T extends Product> T create Product(Class<T> c); 30. } 31. 32. //具体工厂类 33. public class ConcreteCreator extends Creator { 34. public <T extends Product> T create Product(Class<T> c){ 35. Product product=null; 36. try { 37. product = (Product)Class.forName(c.get Name()).new Instance(); 38. } catch (Exception e) { 39. //异常处理 40. } 41. return (T)product; 42. } 43. } 测试代码如下: [java] view plain copy 1. public class Client { 2. public static void main(String[] args) { 3. Creator creator = new ConcreteCreator(); 4. Product product = creator.createProduct(ConcreteProduct1.class); 5. /* 6. * 继续业务处理 7. */ 8. } 9. }
可以看到,工厂方法模式中,在具体的工厂中使用了反射机制来创建了一个product的对象。
以上就介绍了JAVA的相关知识,希望对JAVA有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言JAVA频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号