java中的反射总结.docx
- 文档编号:23492160
- 上传时间:2023-05-17
- 格式:DOCX
- 页数:18
- 大小:226.22KB
java中的反射总结.docx
《java中的反射总结.docx》由会员分享,可在线阅读,更多相关《java中的反射总结.docx(18页珍藏版)》请在冰豆网上搜索。
java中的反射总结
Class类
如果要完成反射,那么必须了解Class类
实例1:
通过对象取得包名和类名
1
2
3
4
5
6
7
8
9
10
11
12
13
package org.siu;
class Test{
}
public class Demo{
public static void main(String[]args){
Testt= new Test();
System.out.println(t.getClass());
System.out.println(t.getClass().getName());
}
}
编译结果如下,注意包的编译方式即可
此处的getClass()方法是默认继承自Object类的
在java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例
因此,这样一来就会牵扯到向上转型和向下转型的概念
由于向下转型的不安全因素,在这里泛型也会接踵而来
(不过我想说的是,此处的泛型设计很刺眼!
尼玛,整个java的语法设计同样刺眼,超恶心!
!
!
)
实例2:
Class类的实例化
由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式:
对象.getClass()
类.Class
forName()
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
class Test{
}
public class Demo{
public static void main(String[]args){
//方式一:
Testt= new Test();
Class
extends Test>c1=t.getClass();
System.out.println(c1);
//方式二:
//为了避免特殊性,这里不用Test类,而用java库中的String类
Class
System.out.println(c2);
//方式三:
//forName()方法会抛出异常
Class
>c3= null;
try {
c3=Class.forName("Test");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
System.out.println(c3);
}
}
其中,forName()方法需要重点掌握,因为它可以在类不确定的情况下实例化Class,更具灵活性
Class类的应用
Class类中有一个方法叫做newInstance(),它可以用来创建一个Class类对象的新实例
怎么说呢?
Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象)
实例3:
Class类的无参构造对象
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
public class Demo{
public static void main(String[]args){
//实例化Class对象,forName()方法会抛异常
Class
>c= null;
try {
//这里需要完整的包名和类名
c=Class.forName("java.lang.String");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
//生成一个字符串的引用
Strings= null;
try {
//将构造好的对象向下转型为String类
//newInstance()方法会抛异常
s=(String)c.newInstance();
} catch (InstantiationExceptione){
e.printStackTrace();
} catch (IllegalAccessExceptione){
e.printStackTrace();
}
System.out.println("字符串长度:
" +s.length());
}
}
这样就通过无参数的形式构造了一个新的对象,如同正常模式中
通过无参构造方法来构造新对象一样
我们知道,类中除了有无参构造方法,还会存在有参数的构造方法
那在反射中如何通过有参数的形式构造对象呢?
接着看
实例4:
Class类的有参构造对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.lang.reflect.Constructor;
public class Demo{
//下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了
public static void main(String[]args) throws Exception{
Class
>c= null;
try {
c=Class.forName("java.lang.String");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
char[]ch={'h','e','l','l','o'};
Strings= null;
//获得Class类对象的有参构造方法,括号里面参数的写法是:
类型.class
Constructor
>con=c.getConstructor(char[].class);
//用此构造方法构造一个新的字符串对象,参数为一个char数组
s=(String)con.newInstance(ch);
System.out.println("构造的字符串:
" +s);
}
}
我们还是使用String类做例,因为String类用的比较多,便于理解
这里需要注意的是,构造方法需要使用getConstructor()方法获得
至于参数类型则是:
原有类型.class
还有一点,无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在
那么,如何才能知道原有类里面的构造方法,普通方法,继承的父类等详细信息呢?
接着看
获取类的结构
要通过反射获取类的结构我们这里要导入一个新的包java.lang.reflect
实例5:
取得类的构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.lang.reflect.Constructor;
import java.util.Arrays;
public class Demo{
//下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了
public static void main(String[]args) throws Exception{
Class
>c= null;
try {
c=Class.forName("java.lang.Boolean");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
//这里的getConstructors()方法返回的是一个Constructor数组
Constructor
>[]cons=c.getConstructors();
//打印的方式你可以自己写,为了方便我用Arrays.toString(),凑合着看
System.out.println(Arrays.toString(cons));
}
}
我选择了Boolean类来做例,因为Boolean类的构造方法就两个,方便看
实例6:
取得类所实现的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Arrays;
public class Demo{
public static void main(String[]args) throws Exception{
Class
>c= null;
try {
c=Class.forName("java.lang.Boolean");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
Class
>[]in=c.getInterfaces();
System.out.println(Arrays.toString(in));
}
}
没什么好说的,看结果
实例7:
取得父类
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo{
public static void main(String[]args) throws Exception{
Class
>c= null;
try {
c=Class.forName("java.lang.Boolean");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
//注意了,这里不会是数组,why?
Class
>su=c.getSuperclass();
System.out.println(su);
}
}
别忘了,java中是单继承,父类只有一个
实例8:
取得类的全部方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.lang.reflect.Method;
public class Demo{
public static void main(String[]args) throws Exception{
Class
>c= null;
try {
c=Class.forName("java.lang.Boolean");
} catch (ClassNotFoundExceptione){
e.printStackTrace();
}
Method[]m=c.getMethods();
//好吧,这次我就大发慈悲的写个打印列表出来
for (int i= 0;i System.out.println(m[i]); } } } 截取一部分,看看,意思下就行了……这几个例子都比较简单 实例9: 取得本类的全部属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.lang.reflect.Field; class Person{ private Stringname; private int age; } public class Demo{ public static void main(String[]args) throws Exception{ Class >c= null; try { c=Class.forName("Person"); } catch (ClassNotFoundExceptione){ e.printStackTrace(); } Field[]f=c.getDeclaredFields(); for (int i= 0;i System.out.println(f[i]); } } } getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性 实例10: 获取本类中属性的值 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 import java.lang.reflect.Field; class Person{ public Stringname; private int age; public Person(Stringname, int age){ this.name=name; this.age=age; } } public class Demo{ public static void main(String[]args) throws Exception{ Personp= new Person("zhangsan",12); Class >c=p.getClass(); //获取公共属性的值 Fieldf1=c.getField("name"); //get(p)表明要获取是哪个对象的值 Stringstr=(String)f1.get(p); System.out.println("姓名: " +str); //获取私有属性的值 Fieldf2=c.getDeclaredField("age"); //age是私有属性,所以要设置安全检查为true f2.setAccessible(true); int age=(int)f2.get(p); System.out.println("年龄: " +age); } } 要注意的是: setAccessible()方法可以设置是否访问和修改私有属性 坦白说,java学到现在我还没发现什么能亮瞎我钛金眼的知识在里边 每次都是写一堆繁琐的语法实现个小玩意儿,不然就是拼命调用API,拼命的抛异常 让本身显得不够紧凑的代码变得愈发累赘 如果我喜欢一门语言,在我利用它做出东西来之前,它本身的特性必须能够打动我 显然,java并不让我快乐,也许很多程序员跟我一样是被迫使用java的 仅以此来安抚我那颗孤独编码的心,下面接着看内容 反射的应用 实例11: 通过反射修改属性 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; class Person{ private Stringname; public Person(Stringname){ this.name=name; } public StringtoString(){ return "姓名: " + this.name; } } public class Demo{ public static void main(String[]args) throws Exception{ Personp= new Person("王二狗"); System.out.println(p); Class >c=p.getClass(); //定义要修改的属性 Fieldf=c.getDeclaredField("name"); f.setAccessible(true); //修改属性,传入要设置的对象和值 f.set(p, "张二蛋"); System.out.println(p); } } 几个方法都是有联系的,如果看不懂就先熟悉上面几个例子 实例12: 通过反射调用方法 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.Method; class Person{ public void print(int i){ System.out.println("我在写数字: " +i); } public static void say(Stringstr){ System.out.println("我在说: " +str); } } public class Demo{ public static void main(String[]args) throws Exception{ Personp= new Person(); Class >c=p.getClass(); //getMethod()方法需要传入方法名,和参数类型 Methodm1=c.getMethod("print", int.class); //invoke()表示调用的意思,需要传入对象和参数 m1.invoke(p, 10); Methodm2=c.getMethod("say",String.class); //这里的null表示不由对象调用,也就是静态方法 m2.invoke(null, "你妹"); } } 这里演示了一个普通的有参方法和一个静态方法 既然有参数的都写出来了,那么无参的就更简单了,直接传入一个对象即可 实例13: 通过反射操作数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.lang.reflect.Array; public class Demo{ public static void main(String[]args) throws Exception{ int[]arr={1,2,3,4,5}; Class >c=arr.getClass().getComponentType(); System.out.println("数组类型: " +c.getName()); int len=Array.getLength(arr); System.out.println("数组长度: " +len); System.out.print("遍历数组: "); for (int i= 0;i System.out.print(Array.get(arr,i)+ ""); } System.out.println(); //修改数组
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java 中的 反射 总结