Java从零开始学四十一(反射简述二)
一、实例化Class类对象
实例化Class类对象的方法有三种:
- 第一种:通过forName()方法
- 第二种:类.class
- 第三种:对象.getClass()
二、Class类的常用方法
No.
|
方法
|
类型
|
描述
|
1
|
public static Class<?> forName(String className) throws ClassNotFoundException
|
普通
|
传入完整的“包.类”名称实例化Class对象
|
2
|
public Constructor[] getConstructors() throws SecurityException
|
普通
|
得到一个类中的全部构造方法
|
3
|
public Field[] getDeclaredFields() throws SecurityException
|
普通
|
得到一个类父类中的全部属性
|
4
|
public Field[] getFields() throws SecurityException
|
普通
|
取得本类的全部属性
|
5
|
public Method[] getMethods() throws SecurityException
|
普通
|
得到一个类中的全部方法
|
6
|
public Method getMethod(String name,Class... parameterTypes)
throws NoSuchMethodException,SecurityException
|
普通
|
返回一个Method对象,并设置一个方法中的所有参数类型
|
7
|
public Class[] getInterfaces()
|
普通
|
得到一个类中所实现的全部接口
|
8
|
public String getName()
|
普通
|
得到一个类完整的“包.类”名称
|
9
|
public Package getPackage()
|
普通
|
得到一个类的包
|
10
|
public Class getSuperclass()
|
普通
|
得到一个类的父类
|
11
|
public Object newInstance() throws InstantiationException,IllegalAccessException
|
普通
|
根据Class定义的类实例化对象
|
12
|
public Class<?> getComponentType()
|
普通
|
返回表示数组类型的Class
|
13
|
public boolean isArray()
|
普通
|
判断此Class是否是一个数组
|
三、获取类的信息
package com.pb.reflect; /* * 1.包 * 2.注解 * 3.构造方法 * 4.方法 * 5.内部类 */ @Deprecated public class ReflectDemo2 { //私有的构造方法 private ReflectDemo2(){}; //公有的带一个一个name属性的构造方法 public ReflectDemo2(String name){ }; //无参数的info方法 public void info(){}; //有参数的info方法 public void info(String str){}; //内部类 class inner{}; }
测试类
package demo; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import com.pb.reflect.ReflectDemo2; public class Demo3 { public static void main(String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException { //获取ReflectDemo2的Class对象 Class<ReflectDemo2> cla=ReflectDemo2.class; //获取ReflectDemo2中全部构造方法 Constructor[] constructors=cla.getDeclaredConstructors(); for (Constructor con : constructors) { System.out.println(con); } //获取指定的公有构造方法 System.out.println("====获取指定的公有构造方法========"); Constructor [] pub=cla.getConstructors(); for (Constructor c : pub) { System.out.println(c.toString()); } //获取公有的方法 System.out.println("====获取公有的方法======"); Method [] methods=cla.getMethods(); for (Method meth : methods) { System.out.println(meth.toString()); } //获取指定方法 System.out.println("====获取指定的的方法======"); //获取info不带参数方法 Method method=cla.getMethod("info",null); System.out.println(method.toString()); //获取info带一个String参数的方法 Method meth=cla.getMethod("info", String.class); System.out.println(meth.toString()); System.out.println("=====获取注释======="); Annotation [] annotations=cla.getAnnotations(); for (Annotation anno : annotations) { System.out.println(anno.toString()); } //获取得包信息 System.out.println("=====获取得包信息======="); Package pack=cla.getPackage(); System.out.println(pack.toString()); //获取内部类 System.out.println("=====获取内部类======="); Class [] clas=cla.getDeclaredClasses(); for (Class c : clas) { System.out.println(c.toString()); } System.out.println("=====获取父类======="); Class class2=cla.getSuperclass(); System.out.println(class2.toString()); //获取内部类的对象 Class innercla=Class.forName("com.pb.reflect.ReflectDemo2$inner"); System.out.println("内部类对应的外部类:"+innercla.getDeclaringClass()); System.out.println("内部类的包:"+innercla.getPackage()); System.out.println("内部类的父类:"+innercla.getSuperclass()); } }
四、创建对象
直接使用newInstance方法创建对象
package demo; import java.util.Date; public class Demo4 { public static void main(String[] args) throws InstantiationException, IllegalAccessException { //获取Date类的Class对象 Class cla=Date.class; //使用newInstrance方法创建对象 Date date=(Date) cla.newInstance(); System.out.println(date.toString()); } }
指定的构造方法创建对象
package demo; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Date; public class Demo4 { public static void main(String[] args) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException { //获取Date类的Class对象 Class cla=Date.class; //获取指定参数的构造方法带一个长整型参数的构造方法 Constructor constructor=cla.getConstructor(long.class); //使用newInstrance方法创建对象 Date date=(Date) constructor.newInstance(1999); System.out.println(date.toString()); } }
五、调用方法
package com.pb.reflect; public class Person { private String name; private String gender; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSay(){ return this.name+" \t"+this.gender+"\t"+this.age; } }
测试类
package demo; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import com.pb.reflect.Person; public class Demo6 { public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { //得到Person类的Class对象 Class cla=Person.class; //声明一个Person对象 Person p=new Person(); //调用setName方法 Method method=cla.getMethod("setName", String.class); //使用invoke赋值 method.invoke(p, "张三"); //调用setGender方法 Method setGender=cla.getMethod("setGender", String.class); setGender.invoke(p, "女"); //调用setAge方法 Method setAge=cla.getMethod("setAge", int.class); setAge.invoke(p, 23); //调用get方法 get方法没有参数设置为null Method getName=cla.getMethod("getName", null); Object o=getName.invoke(p, null); System.out.println(o.toString()); Method getGender=cla.getMethod("getGender", null); Object o1=getGender.invoke(p, null); System.out.println(o1.toString()); Method getAge=cla.getMethod("getAge", null); Object o2=getAge.invoke(p, null); System.out.println(o2.toString()); Method say=cla.getMethod("getSay", null); Object o3=say.invoke(p, null); System.out.println(o3.toString()); } }
结果:
张三 女 23 张三 女 23
六、调用属性
package com.pb.reflect; public class Person { private String name; private String gender; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSay(){ return"姓名:"+this.name+" \t性别:"+this.gender+"\t年龄:"+this.age; } }
测试类
package demo1; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Calendar; import com.pb.reflect.Person; public class Test2 { public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { //声明Person对象 Person p=new Person(); //通过反射重到Person的Class对象 Class cla=Person.class; //因为Person类的属性都是私有的要用getDeclaredField Field name=cla.getDeclaredField("name"); //临时取消权限检查 name.setAccessible(true); name.set(p, "张三丰"); //获取年龄 Field gender=cla.getDeclaredField("gender"); //临时取消权限检查 gender.setAccessible(true); //赋值 gender.set(p, "男"); //获取年龄 Field age=cla.getDeclaredField("age"); age.setAccessible(true); age.setInt(p, 108); //获取say方法 Method getSay=cla.getMethod("getSay", null); Object o=getSay.invoke(p, null); System.out.println(o.toString()); } }
实际在在使用已知类时没有必要使用反射,只有在程序需要动态创建某个类的对象的时候我们才会考虑使用反射
七、动态创建和访问数组
package demo1; import java.lang.reflect.Array; public class ArrayTest1 { /** * 动态创建数组和访问数组 */ public static void main(String[] args) { //创建一个类型为String 的数组长度为10 Object arr=Array.newInstance(String.class, 10); //依次为arr赋值 Array.set(arr, 0, "一"); Array.set(arr, 1, "二"); Array.set(arr, 2, "三"); Array.set(arr, 3, "四"); Array.set(arr, 4, "五"); Array.set(arr,5, "六"); Array.set(arr, 6, "七"); Array.set(arr, 7, "八"); Array.set(arr, 8, "九"); Array.set(arr, 9, "十"); //获取值 Object o8=Array.get(arr, 8); System.out.println("数组 中下标为8的值为"+o8); Object o2=Array.get(arr, 2); System.out.println("数组 中下标为2的值为"+o2); } }
public static void main(String[] args) { // 创建一个一维数组 Object arr1=Array.newInstance(int.class, 10); //为下标为5,和8的赋值 Array.setInt(arr1, 5, 5); Array.setInt(arr1, 8, 8); //查看相应位置的内容 System.out.println(Array.get(arr1, 5)); System.out.println(Array.get(arr1, 8)); }
创建多维数组
package demo1; import java.lang.reflect.Array; public class ArrayTest2 { /** * 使用Array类创建二维数组 */ public static void main(String[] args) { // 创建一个二维数组5,10 Object arr1=Array.newInstance(String.class, 5,10); //为二维数组赋值 //首先获取一维的维灵敏 Object firstIndex=Array.get(arr1, 4); //4,6赋值 Array.set(firstIndex, 6,"张三"); //为3,8赋值 Object new_firstindex=Array.get(arr1, 3); Array.set(new_firstindex, 8, "李四"); //值输出 //将arr1数组强转为2维数组 String [][] str=(String [][])arr1; System.out.println(str[4][6]); System.out.println(str[3][8]); } }