反射的概念:
一般情况下,必须知道一个类的完整路径之后才可以实例化对象,但是java中也允许通过一个对象来找到其所在类的信息,那么实际上就是class的功能。
Object类中定义了一下方法,此方法将被所有子类继承:
public final Class getClass()
以上方法返回值的类型是一个class类,实际上反射从程序的运行结果看就是:可以通过对象反射求出类的名称!
正常方式:引入需要的‘包.类’名称→通过new实例化→取得实例化对象
反射方式:实例化对象→getClass方法→得到完整的“包.类名”名称
Class类
class本身表示一个类的本身,通过class 可以得到一个类中的完整结构,包括此类中的方法定义,属性定义等。
【注意】该类的构造方法被私有化了
实例化class类对象:
第一种:通过forName()
第二种:类.Class
第三种:对象.Class()
Class主要是反射的源头,不光可以取得对象所在类的信息 。也可以直接通过Class类的方法进行对象的实例化操作正常情况下,使用关键字new为对象实例化;若已经实例化好了Class对象,则可以通过Class类中提供的
public newInstance()方法
package com.java.reflect;
class Person {
private String name;
private int age;
/**
* 以下操作要注意:操作类中必须存在无参构造方法,否则无法实例化。以下代码如果被取消注释,则会编译出错
* */
// public Person(String name, int age) {
// this.setAge(age);
// this.setName(name);
// }
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 String toString() {
return "姓名:" + this.name + "\t" + "年龄:" + this.age;
}
}
public class InstanceDemo1 {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException {
Class<?> c = null;// 声明Class对象
try {
c = Class.forName("com.java.reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person per = null;// 声明person对象
try {
per = (Person) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
per.setName("mike");
per.setAge(20);
System.out.println(per);
}
}
为了解决操作类中比需要有无参的构造方法,可以使用getConstructors方法
步骤:①通过Class 类中的getConstructors()取得本类中的全部构造方法,
②向构造方法中传递一对象数组进去,里面包含了构造方法中所需的各个参数
③之后通过Constructor实例化对象
示例程序:
package com.java.reflect;
interface China {
public static final String NATIONAL = "China";// 定义全局常量
public static final String AUTHOR = "李兴华";// 定义全局常量
public void sayChina();
public String sayHello(String name, int age);
}
public class PersonDemo1 implements China {
private String name;
private int age;
public PersonDemo1() {// 无参构造方法
}
public PersonDemo1(String name) {// 设置name属性
this.setName(name);
}
public PersonDemo1(String name, int age) {
this(name);// 调用只有name一个参数的构造函数
this.setAge(age);
}
@Override
public void sayChina() {// 覆写方法
System.out.println("作者" + AUTHOR + "国籍" + NATIONAL);
}
@Override
public String sayHello(String name, int age) {
return name + ",你好!我今年:" + 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;
}
}
3.1取得类所实现的全部接口
使用Class类中的GetInterface方法,因为一个类可以同时实现多个接口,所以在此处将以一个数组的形式返回实现的全部接口!
package com.java.reflect;
public class GetInterfaceDemo {
public static void main(String[] args) {
Class<?> c1 = null;// 声明Class对象
try {
c1 = Class.forName("com.java.reflect.PersonDemo1");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Class<?> c[] = c1.getInterfaces();// 以数组形式返回实现全部接口
for (int i = 0; i < c.length; i++) {
System.out.println("实现接口名称:" + c[i].getName());// 输出接口名称
}
}
}
3.2取得父类
package com.java.reflect;
public class GetSuperClassDemo {
public static void main(String[] args) {
Class<?> c1 = null;
try {
c1 = Class.forName("com.java.reflect.PersonDemo1");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?> c2 = c1.getSuperclass();// 取得父类
System.out.println("父类的名称" + c2.getName());
}
}
3.3取得类的全部构造方法
GetConstructors【类似于getinterface】
package com.java.reflect;
import java.lang.reflect.Constructor;
public class GetConstructors {
public static void main(String[] args) {
Class<?> c1 = null;
try {
c1 = Class.forName("com.java.reflect.PersonDemo1");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Constructor<?> con[] = c1.getConstructors();// 取得一个类中的全部构造方法
for (int i = 0; i < con.length; i++) {
Class<?> p[] = con[i].getParameterTypes();// 得到构造方法中所有的参数
System.out.println("取得构造方法名称");
System.out.println(con[i].getModifiers());// 输出构造,直接打印
System.out.println("参数类型" + con[i].getName());// 取得构造方法的名字
for (int j = 0; j < p.length; j++) {
System.out.println(p[j].getName() + ":arg" + i);
if (j < p.length - 1) {
System.out.println(",");
}
}
}
}
}
还原修饰符:
在上面程序运行之后,取得的权只是一个数字,而不是关键字,因为java在对方法进行修饰时是使用数字抽象而来,而想要把这个数字还原成关键字,必须使用Modifier类完成,此类定义在java.lang.refelct包中,
public static String toString(int mod)
int no =con[i].getModifiers();//取出权限
System.out.println(Modifier.toString(no));//还原权限
3.4取得全部方法
要去的一个类中全部的方法,可以使用Class类中的getDeclaredMethods()方法,此方法返回一个Method类的对象数组,而要进一步取得方法的必须具体信息,就需要Method类。
package com.java.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class GetAllMethodsDemo {
public static void main(String[] args) {
Class<?> c1 = null;
try {
c1 = Class.forName("com.java.reflect.PersonDemo1");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Method m[] = c1.getMethods();// 取得全部方法
for (int i = 0; i < m.length; i++) {
Class<?> r = m[i].getReturnType();// 得到返回值类型
Class<?>[] p = m[i].getParameterTypes();// 取得全部参数类型
int xx = m[i].getModifiers();// 得到修饰符
System.out.println("修饰符" + Modifier.toString(xx));
System.out.println(r + " ");
System.out.println(m[i].getName());
System.out.println(")");
for (int j = 0; j < p.length; j++) {
System.out.println(p[j].getName() + "" + "arg" + j);
if (j < p.length - 1) {
System.out.println(",");
}
}
Class<?> ex[] = m[i].getExceptionTypes();// 取出异常
if (ex.length > 0) {
System.out.println(")throws");
} else {
System.out.println(")");
}
for (int j = 0; j < ex.length; j++) {
System.out.println(ex[j].getName());
}
}
}
}
在反射操作中也同样可以取得一个类中的全部属性,但是在取得属性的时会有两种不同的操作:
得到实现的接口或者父类中的公共属性:public Field[] getFields() throws SecurrityException
得到本类中的全部属性:public Field[] getDeclaredFileds() therows SecurityException
以上方法返回的都是Field的属性,每一个Field对象就表示类中的一个属性 ;
package com.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class GetFieldDemo {
public static void main(String[] args) {
Class<?> c1 = null;
try {
c1 = Class.forName("com.java.reflect.PersonDemo1");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Field f[] = c1.getFields();// 取得本类中的属性
for (int i = 0; i < f.length; i++) {
Class<?> r = f[i].getType();// 得到属性类型
int no = f[i].getModifiers();
String priv = Modifier.toString(no);// 还原修饰符
System.out.println("公共属性" + priv + " ");
System.out.println(r.getName() + " ");// 得到属性类型
System.out.println(f[i].getName());
}
}
}