初识反射机制
以前我们访问对象的方法和属性,都是在编译期的时候完成的。但Java可不可以在运行期来实现调用某个类的方法和属性,这个当然是可以的,Java就是通过反射来实现的,反射的英文是Reflection。
Java 反射机制主要提供了以下功能:
• 在运行时判断任意一个对象所属的类。
• 在运行时构造任意一个类的对象。
• 在运行时判断任意一个类所具有的成员变量和方法。
• 在运行时调用任意一个对象的方法
• 在运行时构造任意一个类的对象。
• 在运行时判断任意一个类所具有的成员变量和方法。
• 在运行时调用任意一个对象的方法
下面我来说一下Java是如何来完成这个工作了。
我们首先来介绍一个最基本的类Class类。
反射的基础--------Class类
在Java中每个类都有一个且仅有一个Class对象,不管这个类生成多少个新的对象,他都只有一个。这个对象描述了这个类的包括名称在内的一些信息,要想使用反射必须先得到Class对象。下面我们写个程序来测试一下。我们来以String类测试一下:
package reflection;
public class TestOne {
public static void main(String[] args) {
Class classType = String.class;
System.out.println(classType);
}
}
这个测试程序的结果如下:
class java.lang.String
得到Class对象的三种方法
•第一种
因为所有的类都直接或间接的继承自Object类,而Object中有一个方法getClass()方法,这个方法可以得到这个对象所对应的类的Class对象,我们还是以String类为例:
package reflection;
public class TestOne {
public static void main(String[] args) {
String str ="滨州学院csdn高校俱乐部";
Class classType = str.getClass();
System.out.println(classType);
}
}
这个测试程序的结果如下:
class java.lang.String
Class类本身有个静态方法:
public static Class<?> forName(String className)这个方法可以返回与带有给定字符串名的类或接口相关联的
Class
对象。测试一下:
package reflection;
public class TestOne {
public static void main(String[] args) throws Exception {
Class classType = Class.forName("java.lang.String");
System.out.println(classType);
}
}
这个测试程序的结果如下:
class java.lang.String
使用类的.class 语法,也可以得到Class对象,就像我第一个例子一样,我就不再演示了。
Class还有以下几个方法:
– getName():获得类的完整名字。
– getFields():获得类的public类型的属性。
– getDeclaredFields():获得类的所有属性。
– getMethods():获得类的public类型的方法。
– getDeclaredMethods():获得类的所有方法。
– getFields():获得类的public类型的属性。
– getDeclaredFields():获得类的所有属性。
– getMethods():获得类的public类型的方法。
– getDeclaredMethods():获得类的所有方法。
– getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
– getConstructors():获得类的public类型的构造方法。
– getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
– newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
– getConstructors():获得类的public类型的构造方法。
– getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
– newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
下面来讲一下通过默认构造方法创建一个新对象:
例:
package reflection;
public class TestOne {
public static void main(String[] args) throws Exception {
Class classType = Class.forName("java.lang.String");
String str =(String) classType.newInstance();
}
}
因为newInstance()方法的返回值是Object类型,所以需要强制转换,或者使用泛型:
package reflection;
public class TestOne {
public static void main(String[] args) throws Exception {
Class<String> classType = String.class;
String str =classType.newInstance();
}
}
调用构造方法,普通方法,属性的类-------Constructor 类,Method类,Field 类
刚刚我们演示了通过默认构造方法创建一个新对象,但如果想要通过一个类的有参数的构造方法来创建一个对象,就必须通过
Constructor 类。用这个类来调用有参构造的方式如下例:
package reflection;
import java.lang.reflect.*;
class A
{
public A(int a)
{}
}
public class TestOne {
public static void main(String[] args) throws Exception {
Class<A> classType = A.class;
Constructor<A> con = classType.getConstructor(new Class[]{int.class});
A a = con.newInstance(new Object[]{1});
}
}
Class类的
package reflection;
import java.lang.reflect.*;
class A
{
public A(int a)
{}
}
public class TestOne {
public static void main(String[] args) throws Exception {
Class<A> classType = A.class;
Constructor<A> con = classType.getConstructor(new Class[]{int.class});
A a = con.newInstance(new Object[]{1});
}
}
getConstructor();方法是用来获取构造方法类的对象,参数是构造方法的参数类型,因为同一个类不同的构造方法只有参数不同,所以这样就可以获取类的构造方法,如果没有参数就是调用无参构造函数。
getConstructor();方法是用来获取构造方法类的对象,参数是构造方法的参数类型,因为同一个类不同的构造方法只有参数不同,所以这样就可以获取类的构造方法,如果没有参数就是调用无参构造函数。
创建了对象后我们就要调用他的方法和属性,分别用到了
创建了对象后我们就要调用他的方法和属性,分别用到了
Method类,Field 类。
Method类,Field 类。
调用方法:
package reflection;
import java.lang.reflect.*;
class A
{
public int a;
public A(int a)
{
this.a = a;
}
public void b()
{
a = 2;
}
}
public class TestOne {
public static void main(String[] args) throws Exception {
Class<A> classType = A.class;
Constructor<A> con = classType.getConstructor(new Class[]{int.class});
A a = con.newInstance(new Object[]{1});
Method met = classType.getMethod("b", new Class[]{});
met.invoke(a, new Object[]{});
}
}
调用属性
package reflection;
import java.lang.reflect.*;
class A
{
public int a;
public A(int a)
{
this.a = a;
}
public void b()
{
a = 2;
}
}
public class TestOne {
public static void main(String[] args) throws Exception {
Class<A> classType = A.class;
Constructor<A> con = classType.getConstructor(new Class[]{int.class});
A a = con.newInstance(new Object[]{1});
Field fie = classType.getField("a");
fie.set(a, 3);
System.out.println(a.a);
}
}
结果为3.
如果想要调用私有方法,就要像下面这个例子一样:
package reflection;
import java.lang.reflect.*;
class A
{
private int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public A(int a)
{
this.a = a;
}
public void b()
{
a = 2;
}
}
public class TestOne {
public static void main(String[] args) throws Exception {
Class<A> classType = A.class;
Constructor<A> con = classType.getConstructor(new Class[]{int.class});
A a = con.newInstance(new Object[]{1});
Field fie = classType.getDeclaredField("a");
fie.setAccessible(true);
fie.set(a, 3);
System.out.println(a.getA());
}
}
调用私有方法,和这个是同理的。就不再举例子了。
以上就是反射的一些基本内容。