什么是反射
反射的作用
利用反射调用类结构
正:正常情况下,先有类,之后才会有类的对象
反:可以利用对象找到对象的出处
取得Classs对象:
public final Class<?> getClass()
该方法继承自Object类,所以,所有的类都有这个方法
public static void main(String[] args) { Date date = new Date(); System.out.println(date.getClass()); } //输出: //class java.util.Date
java.lang.Class是一个类。该类是反射的源头,该类有三种实例化方法,如下:
调用Object类中的getClass()方法
public static void main(String[] args) { Date date = new Date(); Class <?> cls = date.getClass(); System.out.println(cls); }
使用"类.class"取得
public static void main(String[] args) { Class <?> cls = Date.Class; System.out.println(cls); }
调用Class类提供的方法
实例化Class对象:
public static Class<?> forName(String className)
throws ClassNotFoundException
public static void main(String[] args) { Class <?> cls = Class.forName("java.util.Date"); System.out.println(cls); }
此时可以不使用import进行导入
当拿到一个类的时候,使用new 实例化对象。如果存在Class类对象,就可以通过反射进行对象的实例化
实例化对象方法:
public T newInstance() throws InstantiationException, IllegalAccessException
示例
class Book{ public Book() { System.out.println("********************"); } public String toString() { return "这是一本书"; } } public class test { public static void main(String[] args) throws Exception { //1.常规方法,new对象 Book b = new Book(); System.out.println(b); //2.反射对象 Class<?> cls = Class.forName("com.String.Book"); Object o = cls.newInstance(); Book book = (Book)o; System.out.println(o);//输出b和o结果一样 } }
当类中只有有参构造的时候,通过反射调用,会产生异常
错误代码示例
package com.String; public class test { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("com.t.Book"); Object o = cls.newInstance(); System.out.println(o); } }
Book类,位于其他包
package com.t; public class Book{ private String title; private double price; public Book(String title , double price) { this.title = title ; this.price = price; } public String toString() { return "书名:"+this.title+",价格:"+this.price; } }
异常信息
Exception in thread "main" java.lang.InstantiationException: com.t.Book at java.lang.Class.newInstance(Unknown Source) at com.String.test.main(test.java:11) Caused by: java.lang.NoSuchMethodException: com.t.Book.<init>() at java.lang.Class.getConstructor0(Unknown Source) ... 2 more
解决方法:
在Class类中,提供有获取构造方法的方法
取得全部构造方法:
public Constructor <?> [] getConstructors()
取得一个指定参数的构造方法:
public Constructor < T > getConstructor(Class<?>… parameterTypes)
上面两个方法的返回值**Constructor **是java.lang.reflect.Constructor类的对象,在这个类中提供有一个明确传递有参构造内容的实例化对象方法
public T newInstance(Object... initargs)
解决代码示例:
package com.String; import java.lang.reflect.Constructor; public class test { public static void main(String[] args) throws Exception { Class<?> cls = Class.forName("com.t.Book"); Constructor<?> con = cls.getConstructor(String.class,double.class); Object o = con.newInstance("java开发",79.8); System.out.println(o); } }
简单JAVA类的开发之中,至少保留一个无参构造,反射调用不方便
类中的普通方法,只有在类产生实例化对象之后才可以调用。
实例化对象的方式有三种
在Class类中,提供有取得方法的操作
取得一个类中的全部方法
public Method[] getMethods()
取得指定名称的方法
public Method getMethod(String name, Class<?>... parameterTypes)
name是方法名称
上面两个方法的返回值**Method **是java.lang.reflect.Method 类的对象
调用方法:
public Object invoke(Object obj, Object... args)
示例代码
Book类,位于其他包
package com.t; public class Book{ private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
调用方法:
package com.String; import java.lang.reflect.Method; public class test { public static void main(String[] args) throws Exception { String fielName = "title"; Class<?> cls = Class.forName("com.t.Book"); Object o = cls.newInstance(); Method setMet = cls.getMethod("set" +initcap(fielName), String.class); Method getMet = cls.getMethod("get" +initcap(fielName)); setMet.invoke(o, "java开发"); System.out.println(getMet.invoke(o)); } //首字母大写 public static String initcap(String str) { return str.substring(0, 1).toUpperCase()+str.substring(1); } }
类中的属性,一定要在本类实例化对象产生之后才可以分配内存空间
取得全部成员
public Field[] getDeclaredFields()
取得指定成员
public Field getDeclaredField(String name)
上面两个方法的返回值Field是java.lang.reflect.Field类的对象,该类提供有如下常用方法
取得属性内容
public Object get(Object obj)
设置属性内容
public void set(Object obj,Object value)
使用示例:
Book类,位于其他包
package com.t; public class Book{ private String title; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
反射调用:
package com.String; import java.lang.reflect.Field; public class test { public static void main(String[] args) throws Exception { //1.实例化类对象 Class<?> cls = Class.forName("com.t.Book"); Object o = cls.newInstance(); //取得成员 Field titleField = cls.getDeclaredField("title"); //取消封装,不取消无法访问private变量 titleField.setAccessible(true); //设置成员变量 titleField.set(o, "python"); System.out.println(titleField.get(o)); } }
构造方法和普通方法也可以取消封装