tonglin0325的个人主页

Java反射机制

如果要通过一个对象找到一个类的名称,此时就需要用到反射机制(反射技术是用来做框架的,一般情况下Java私有对象不能被访问,但是暴力反射可以访问私有对象)

任何一个类如果没有明确地声明继承自哪个父类的时候,则默认继承Object类,所以getClass()方法是Object类中的。

文件在包java_reflect目录

 

1
2
3
4
5
6
7
// 类名:Y
// 属性:
// 方法:
class Y{

}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Y{

}

//主类
//Function : GetClass_demo;
public class GetClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Y y = new Y();
System.out.println(y.getClass().getName());
}

}

 输出  

 

 

 

 

实例化Class类对象的3种方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Y{

}

public class GetClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根

Class<?> c1 = null;
Class<?> c2 = null;
Class<?> c3 = null;
try{
c1 = Class.forName("java_basic.Y"); //通过forName()方法实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace();
}

c2 = new Y().getClass(); //通过Object类中的方法实例

c3 = Y.class; //通过类.class实例化
System.out.println("类名称"+c1.getName());
System.out.println("类名称"+c2.getName());
System.out.println("类名称"+c3.getName());
}

}

** 输出   **

 

Class类的使用

Class类在开发中最常见的用法就是实例化对象的操作,即可以通过一个给定的字符串(此字符串包含了完整的“包.类”的路径)来实例化一个类的对象

 

**  1.通过无参构造实例化对象**

如果要想通过Class类对象实例化其他类的对象,则可以使用newInstance()方法,但是必须要保证被实例化的类中存在一个无参构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class InstanceClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c = null; //指定泛型
try{
c = Class.forName("person"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}
person per = null; //声明person对象
try{
per = (person)c.newInstance(); //实例化person对象
}catch(Exception e){
e.printStackTrace();
}
per.setAge(30);
per.setName("张三");
System.out.println(per);
}

}

输出  

 

**  2.调用有参构造实例化对象**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.lang.reflect.Constructor;

public class InstanceClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c = null; //指定泛型
try{
c = Class.forName("person"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}
person per = null; //声明person对象
Constructor<?> cons[] = null; //声明一个表示构造方法的数组
cons = c.getConstructors(); //通过反射取得全部构造
try{
per = (person) cons[0].newInstance("张三",30); //实例化person对象
}catch(Exception e){
e.printStackTrace();
}
// per.setAge(30);
// per.setName("张三");
System.out.println(per);
}

}

 输出  

 

可以通过反射得到一个类的完整结构,需要使用到java.lang.reflect包中的以下几个类。

Constructor:表示类中的构造方法

Field:表示类中的属性

Method:表示类中的方法

这3个类都是AccessibleObject类中的子类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
interface China{
public static final String NATIONAL = "China";
public static final String AUTHOR = "张三";
public void sayChina();
public String sayHello(String name,int age);
}

class Person_5 implements China{

private String name;
private int age;

public Person_5(){ //无参构造方法

}

public Person_5(String name) { //声明两个参数的构造方法
super();
this.name = 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 Person_5(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public void sayChina() {
// TODO 自动生成的方法存根
System.out.println("作者:"+AUTHOR+"国籍:"+NATIONAL);
}

@Override
public String sayHello(String name, int age) {
// TODO 自动生成的方法存根
return name+"age:"+age;
}



}

public class ConstructorClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}
Class<?> c[] = c1.getInterfaces(); //取得实现的全部接口
for(int i=0;i<c.length;i++){
System.out.println("实现的接口名称:"+c[i].getName());
}

}

}

 

取得父类

一个类可以实现多个接口,但是只能继承一个父类,所以如果要取得一个类的父类,可以直接使用class类中的getSuperclass()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
interface China{
public static final String NATIONAL = "China";
public static final String AUTHOR = "张三";
public void sayChina();
public String sayHello(String name,int age);
}

class Person_5 implements China{

private String name;
private int age;

public Person_5(){ //无参构造方法

}

public Person_5(String name) { //声明两个参数的构造方法
super();
this.name = 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 Person_5(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public void sayChina() {
// TODO 自动生成的方法存根
System.out.println("作者:"+AUTHOR+"国籍:"+NATIONAL);
}

@Override
public String sayHello(String name, int age) {
// TODO 自动生成的方法存根
return name+"age:"+age;
}



}

public class ConstructorClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}

Class<?> c2 = c1.getSuperclass(); //取得父类
System.out.println("实现的接口名称:"+c2.getName());
}

}

 

取得全部构造方法

要取得一个类中的全部构造方法,则必须使用Class类中的getConstructors()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.lang.reflect.Constructor;

interface China{
public static final String NATIONAL = "China";
public static final String AUTHOR = "张三";
public void sayChina();
public String sayHello(String name,int age);
}

class Person_5 implements China{

private String name;
private int age;

public Person_5(){ //无参构造方法

}

public Person_5(String name) { //声明两个参数的构造方法
super();
this.name = 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 Person_5(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public void sayChina() {
// TODO 自动生成的方法存根
System.out.println("作者:"+AUTHOR+"国籍:"+NATIONAL);
}

@Override
public String sayHello(String name, int age) {
// TODO 自动生成的方法存根
return name+"age:"+age;
}



}

public class ConstructorClass_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}

Constructor<?> c[] = c1.getConstructors(); //取得全部的构造方法
for(int i=0;i<c.length;i++){
System.out.println("全部的构造方法:"+c[i]);
}
}

}

 

取得全部方法

要取得一个类中的全部方法,可以使用Class类中的getMethods()方法,此方法返回一个Method类的对象数组。

如果要进一步取得方法的具体信息,例如,方法的参数、抛出的异常声明等,则就必须依靠Method类。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class GetMethod_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
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(); //得到方法的修饰符,即public

System.out.print(Modifier.toString(xx)+" "); //还原修饰符
System.out.print(r.getName()+" "); //得到方法返回值
System.out.print(m[i].getName()); //取得方法的名称
System.out.print("(");
for(int x=0;x<p.length;x++){
System.out.print(p[x].getName()+" "+"arg"+x); //输出参数
if(x<p.length-1){
System.out.print(",");
}
}
Class<?> ex[] = m[i].getExceptionTypes(); //得到全部的异常抛出
if(ex.length>0){ //判断是否有异常
System.out.print(") throws ");
}else{
System.out.print(") ");
}
for(int j=0;j<ex.length;j++){
System.out.println(ex[j].getName()); //输出异常信息
if(j<ex.length-1){
System.out.println(",");
}
}
System.out.println();
}
}

}

 

 

取得全部属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class GetMethod_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
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(); //得到方法的修饰符,即public
//
// System.out.print(Modifier.toString(xx)+" "); //还原修饰符
// System.out.print(r.getName()+" "); //得到方法返回值
// System.out.print(m[i].getName()); //取得方法的名称
// System.out.print("(");
// for(int x=0;x<p.length;x++){
// System.out.print(p[x].getName()+" "+"arg"+x); //输出参数
// if(x<p.length-1){
// System.out.print(",");
// }
// }
// Class<?> ex[] = m[i].getExceptionTypes(); //得到全部的异常抛出
// if(ex.length>0){ //判断是否有异常
// System.out.print(") throws ");
// }else{
// System.out.print(") ");
// }
// for(int j=0;j<ex.length;j++){
// System.out.println(ex[j].getName()); //输出异常信息
// if(j<ex.length-1){
// System.out.println(",");
// }
// }
// System.out.println();
// }

{
Field f[] = c1.getDeclaredFields(); //取得本类属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType(); //取出属性的类型
int mo = f[i].getModifiers(); //得到修饰符数字
String priv = Modifier.toString(mo); //取得属性的修饰符
System.out.print("本类属性:");
System.out.print(priv + " "); //输出修饰符
System.out.print(r.getName()+" "); //输出属性类型
System.out.print(f[i].getName()); //输出属性名称
System.out.println(" ;");
}
}

{
Field f[] = c1.getFields(); //取得父类公共属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType(); //取出属性的类型
int mo = f[i].getModifiers(); //得到修饰符数字
String priv = Modifier.toString(mo); //取得属性的修饰符
System.out.print("本类属性:");
System.out.print(priv + " "); //输出修饰符
System.out.print(r.getName()+" "); //输出属性类型
System.out.print(f[i].getName()); //输出属性名称
System.out.println(" ;");
}
}


}

}

 

反射机制还可以调用类中的指定方法或指定属性,并且可以通过反射完成对数组的操作。

通过反射调用类中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.lang.reflect.Method;

public class InvokeChina_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}
try{
Method met = c1.getMethod("sayChina"); //取得一个Method对象
met.invoke(c1.newInstance()); //使用invoke进行调用,必须传递对象实例
}catch(Exception e){
e.printStackTrace();
}
}

}

 

可以向方法中传递两个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.lang.reflect.Method;

public class InvokeChina_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}
try{

Method met = c1.getMethod("sayHello",String.class,int.class); //此方法需要两个参数
String rv = null; //接收方法的返回值
rv = (String)met.invoke(c1.newInstance(),"李四",32); //使用invoke进行调用,必须传递对象实例
System.out.println(rv);
}catch(Exception e){
e.printStackTrace();
}
}

}

 

调用setter和getter方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.lang.reflect.Method;

public class InvokeSetGet_demo {

public static void main(String[] args) {
// TODO 自动生成的方法存根
Class<?> c1 = null; //指定泛型
Object obj = null; //声明一个对象
try{
c1 = Class.forName("Person_5"); //传入要实例化类的完整包.类名称
}catch(ClassNotFoundException e){
e.printStackTrace();
}
try{
obj = c1.newInstance(); //实例化操作对象
}catch(InstantiationException | IllegalAccessException e){
e.printStackTrace();
}

setter(obj, "name", "张三", String.class);
setter(obj, "age", 25, int.class);
System.out.println("姓名:");
getter(obj, "name");
System.out.println("年龄:");
getter(obj, "age");
}

public static void setter(Object obj,String att,Object value,Class<?> type){
try{
Method met = obj.getClass().getMethod("set"+initStr(att),type); //设置方法参数类型
met.invoke(obj, value); //调用方法
}catch(Exception e){
e.printStackTrace();
}
}

public static void getter(Object obj,String att){
try{
Method met = obj.getClass().getMethod("get"+initStr(att));
System.out.println(met.invoke(obj)); //接收方法的返回值
}catch(Exception e){
e.printStackTrace();
}
}

public static String initStr(String old){
String str = old.substring(0, 1).toUpperCase()+old.substring(1); //首字母大写
return str;

}

}

 

直接操作类中的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.lang.reflect.Field;

public class InvokeField_demo {

public static void main(String[] args) throws Exception {
// TODO 自动生成的方法存根
Class<?> c1 = null; //声明Class对象
Object obj = null; //声明一个对象

c1 =Class.forName("Person_5"); //实例化Class对象
obj = c1.newInstance(); //实例化对象

Field nameField = null; //表示name属性
Field ageField = null; //表示age属性
nameField = c1.getDeclaredField("name"); //取得name属性
ageField = c1.getDeclaredField("age"); //取得age属性

nameField.setAccessible(true); //将name属性设置成可被外部访问
nameField.set(obj, "张三"); //设置name属性内容
ageField.setAccessible(true); //将age属性设置成可被外部访问
ageField.set(obj, 33); //设置age属性内容

System.out.println("姓名:"+nameField.get(obj)); //通过get取得属性内容
System.out.println("年龄:"+ageField.get(obj));
}

}

通过反射操作数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.lang.reflect.Field;
import java.lang.reflect.Array;

public class InvokeField_demo {

public static void main(String[] args) throws Exception {
// TODO 自动生成的方法存根

int temp[] = {1,2,3};
Class<?> c = temp.getClass().getComponentType(); //取得数组的Class对象

System.out.println("类型:"+c.getName()); //得到数组类型名称
System.out.println("长度:"+Array.getLength(temp)); //得到数组长度
System.out.println("第一个内容:"+Array.get(temp,0)); //得到第一个内容
Array.set(temp,0,6); //修改第一个内容
System.out.println("第一个内容:"+Array.get(temp,0)); //得到第一个内容
}

}