反射可以直接获得class对象,可以实现动态创建对象
1、获得class对象的方法
1、调用类的class属性
> Class<?> cls = String.class;//获得String的class对象
> System.out.println("String的class对象:"+cls); cls =
> int.class;//获得int类型的class对象 System.out.println("int的class对象:"+cls);
输出:
String的class对象:class java.lang.String
int的class对象:int
2、调用class中的forName(全类名)方法获得
try {
Class<?> cls2 = Class.forName("java.util.Arrays");
System.out.println("Arrays的class对象:"+cls2);
//从控制台输入一个类名,获得该类名对应的类对象
Scanner sca = new Scanner(System.in);
String className = sca.nextLine();//给的是全类名
Class<?> cls3 = Class.forName(className);
System.out.println(className+"的classs对象"+cls3);
sca.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
输出:
Arrays的class对象:class java.util.Arrays java.lang.Double
java.lang.Double的classs对象class java.lang.Double
完整代码:
public class ReflectDemo01 {
public static void main(String[] args) {
//"?"通配符,不论什么类型都能匹配
Class<?> cls = String.class;//获得String的class对象
System.out.println("String的class对象:"+cls);
cls = int.class;//获得int类型的class对象
System.out.println("int的class对象:"+cls);
try {
Class<?> cls2 = Class.forName("java.util.Arrays");
System.out.println("Arrays的class对象:"+cls2);
//从控制台输入一个类名,获得该类名对应的类对象
Scanner sca = new Scanner(System.in);
String className = sca.nextLine();//给的是全类名
Class<?> cls3 = Class.forName(className);
System.out.println(className+"的classs对象"+cls3);
sca.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、通过class对象创建类的实例
1、先创建一个类person
class Person{
private String name;
private Integer age;
private String sex;
public Person() {}
public Person(String name, Integer age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
2、获得Class对象
//获得class对象
Class<?> cls = Class.forName("reflect.Person");
3、创建实例
(1)通过无参构造创建的实例
Object instance = cls.newInstance();
System.out.println("无参构造创建对象:"+instance);//默认调用类中的toString()方法
输出:因为是无参构造,所以里面是空的
无参构造创建对象:Person [name=null, age=null, sex=null]
(2)通过有参构造创建实例
先获得构造函数,使用getConstructor(parameterTypes)方法,参数是构造函数参数的类型的class对象,是可变参数
Constructor<?> con = cls.getConstructor(String.class,Integer.class,String.class);
然后使用构造函数创建对象
Object o2 = con.newInstance("有参构造创建对象:"+"张三",100,"男");
System.out.println(o2);
输出:
Person [name=有参构造创建对象:张三, age=100, sex=男]
完整代码
public class RefiectDemo02 {
public static void main(String[] args) {
try {
//获得class对象
Class<?> cls = Class.forName("reflect.Person");
/**
* 通过无参构造创建的对象实例
*/
Object instance = cls.newInstance();
System.out.println("无参构造创建对象:"+instance);//默认调用类中的toString()方法
/**
* 通过有参构造方法创建对象
*/
Constructor<?> con = cls.getConstructor(String.class,Integer.class,String.class);//这里的参数是class类型的可变参数
Object o2 = con.newInstance("有参构造创建对象:"+"张三",100,"男");
System.out.println(o2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Person{
private String name;
private Integer age;
private String sex;
public Person() {}
public Person(String name, Integer age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
}
}
3、调用类中的普通方法
1、获得class对象
//获得类对象
Class<?> cls = Class.forName("reflect.Person");
2、获得方法
(1)getMethods()方法获得class对象对应的类中的所有的非私有方法,包括继承过来的方法
Method[] methods = cls.getMethods();
for(Method m : methods) {
//直接输出m的话会输出每个方法的具体信息,包括修饰权限和返回值类型
//getName()获得方法的名字
System.out.println(m.getName());
}
输出结果
(2)getName(methodName,paraType)根据方法名获得方法(有多个重载方法使用),第一个参数是方法名,第二个参数是方法里面的参数类型的class对象,是可变参数,方法没有参数不用传第二个参数
//获得有参构造函数
Constructor<?> con = cls.getConstructor(String.class,Integer.class,String.class);
//根据有参构造创建对象
Object o = con.newInstance("李四",23,"女");
获得person类中的getName()方法
Method getName = cls.getMethod("getName");
调用类中的方法使用invoke()方法,调用之前需要先创建对象
Object s = getName.invoke(o);//得到方法的返回值
System.out.println(s);
输出
李四
获得person类中的setName()方法
Method setName = cls.getMethod("setName",String.class);
Object s2 = setName.invoke(o, "王五");//得到方法的返回值
System.out.println(s2);
输出:因为set方法没有返回值,所以输出为null
null
完整代码
public class ReflectDemo03 {
public static void main(String[] args) {
try {
//获得类对象
Class<?> cls = Class.forName("reflect.Person");
//getMethods()获得类对象对应的类中的所有的方法
Method[] methods = cls.getMethods();
for(Method m : methods) {
//直接输出m的话会输出每个方法的具体信息,包括修饰权限和返回值类型
//getName()获得方法的名字
System.out.println("具体信息:"+m);
System.out.println("方法名:"+m.getName());
}
/**
* getName(methodName,paraType)根据方法名获得方法(有多个重载方法使用),
* 第一个参数是方法名,第二个参数是方法里面的参数类型的class对象,是可变参数
* 方法没有参数不用传第二个参数
*/
Constructor<?> con = cls.getConstructor(String.class,Integer.class,String.class);
Object o = con.newInstance("李四",23,"女");
//获得方法
Method getName = cls.getMethod("getName");
//调用方法使用invoke()方法,调用之前需要先创建对象
Object s = getName.invoke(o);//得到方法的返回值
System.out.println(s);
Method setName = cls.getMethod("setName",String.class);
Object s2 = setName.invoke(o, "王五");//得到方法的返回值
System.out.println(s2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
4、将类中的私有方法设置为可访问
先创建一个测试类
class Test{
private void test1() {
System.out.println("私有方法1");
}
public void test2() {
System.out.println("公有方法1");
}
}
获得class对象
Class<?> cls = Test.class;
getDeclaredMethods()可以获得类中所有定义的方法,不包含继承过来的方法
Method[] methods2 = cls.getDeclaredMethods();
for(Method m:methods2) {
System.out.println(m.getName());
}
输出:
test1
test2
根据方法名字获得类中的私有方法,然后创建对象,使用setAccessible(boolean b)方法,参数为true即可把私有方法设置方法为可访问
Method method = cls.getDeclaredMethod("test1");
//获得根据无参构造创建的类对象
Object o = cls.newInstance();
//setAccessible(boolean b)参数为true即可把私有方法设置方法为可访问
method.setAccessible(true);
method.invoke(o);
完整代码
public class ReflectDemo03 {
public static void main(String[] args) {
try {
//获得类对象
Class<?> cls = Class.forName("reflect.Person");
//getMethods()获得类对象对应的类中的所有的方法
Method[] methods = cls.getMethods();
for(Method m : methods) {
//直接输出m的话会输出每个方法的具体信息,包括修饰权限和返回值类型
//getName()获得方法的名字
System.out.println("具体信息:"+m);
System.out.println("方法名:"+m.getName());
}
/**
* getName(methodName,paraType)根据方法名获得方法(有多个重载方法使用),
* 第一个参数是方法名,第二个参数是方法里面的参数类型的class对象,是可变参数
* 方法没有参数不用传第二个参数
*/
Constructor<?> con = cls.getConstructor(String.class,Integer.class,String.class);
Object o = con.newInstance("李四",23,"女");
//获得方法
Method getName = cls.getMethod("getName");
//调用方法使用invoke()方法,调用之前需要先创建对象
Object s = getName.invoke(o);//得到方法的返回值
System.out.println(s);
Method setName = cls.getMethod("setName",String.class);
Object s2 = setName.invoke(o, "王五");//得到方法的返回值
System.out.println(s2);
} catch (Exception e) {
e.printStackTrace();
}
}
}