java反射初学习
“程序运行时,允许改变程序结构或变量类型,这种语
言称为动态语言”,如Python,Ruby是动态语言;显然
C++,Java,C#不是动态语言,但是JAVA有着一个非常
突出的动态相关机制:Reflection。
JAVA反射机制是在运行状态中,对于任意一个类,都能
够知道这个类的所有属性和方法;对于任意一个对象,
都能够调用它的任意一个方法和属性;这种动态获取的
信息以及动态调用对象的方法的功能称为java语言的反
射机制,很多优秀的开源框架都是通过反射完成的。
Java反射机制,可以实现以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理;
可变参数
/**
\* 入门级示例:通过对象获取 包名.类名
\* @author Administrator
*/
public class Simple {
public static void main(String[] args) {
Simple s=new Simple();
System.out.println(s.2.getName());
}
}
当我们能够确定一系列参数的类型,类型必须是统一
的, 但是我们确定不了参数的个数的时候,我们可以使
用可变参数。可变代表个数可变[0,+),如果一个方法
中带有可变参数,这个可变参数只能在参数列表最后。
获取源头Class(重点)
所有类的对象其实都是Class**的实例。**这个 Class 实例
可以理解为类的模子,就是包含了类的结构信息,类似
于图纸。我们日常生活中,需要创造一个产品,如想山
寨一个iphone手机,怎么办?有三种方式可以实现:
⑴买个iphone手机,拆的七零八落的,开始山寨;
⑵到iphone工厂参观,拿到iphone磨具,开始山寨;
⑶跑到美国盗取iphone的图纸,开始山寨,最后一种最
暴力,最爽。
同理,获取类的Class对象也有三种方式
⑴Class.forName(”包名.类名”) //一般尽量采用该形式
(2)类.class
(3)对象.getClass()
类加载器(了解)
类的生命周期
在一个类编译完成之后,下一步就需要开始使用类,如
果要使用一个类,肯定离不开JVM。在程序执行中JVM通
过装载,链接,初始化这3个步骤完成。
从类的生命周期而言,一个类包括如下阶段:
加载、验证、准备、初始化和卸载这5个阶段的顺序是确
定的,类的加载过程必须按照这种顺序进行
类的装载 是通过 类加载器 完成的,加载器将 .class 文
件的二进制文件装入JVM的方法区,并且在堆区创建描
述这个类的 java.lang.Class 对象。用来封装数据。
但是同一个类只会被类装载器装载一次。
链接 就是把二进制数据组装为可以运行的状态。链接分
为校验,准备,解析这3个阶段
类加载器
顾名思义,类加载器(class loader)用来加载 Java 类到
Java 虚拟机中。一般来说,Java 虚拟机使用 Java 类的
方式如下:Java 源程序(.java 文件)在经过 Java 编译
器编译之后就被转换成 Java 字节代码(.class 文件)。
类加载器负责读取 Java 字节代码,并转换成
java.lang.Class 类的一个实例。每个这样的实例用
来表示一个 Java 类。通过此实例的 newInstance()
方法就可以创建出该类的一个对象。实际的情况可能更
加复杂,比如 Java 字节代码可能是通过工具动态生成
的,也可能是通过网络下载的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f173Onk3-1603201534777)(C:\Users\lwf\AppData\Roaming\Typora\typora-user-images\image-20201020214106170.png)]
在java中有三种类类加载器:
⑴ Bootstrap ClassLoader 此加载器采用c++编写,一般开
发中很少见。⑵ Extension ClassLoader 用来进行扩展类的加载,一般
对应的是jre\lib\ext目录中的类
⑶ AppClassLoader 加载classpath指定的类,是最常用的
加载器。同时也是java中默认的加载器。 了解即可。
public static void main(String[] args) throws
Exception {
System.out.println("类加载器
"+ClassLoader.class.getClassLoader().getClass(
).getName());
}
反射的运用
package com
.lwf
;
import java
.io
.*
;
import java
.lang
.reflect
.Constructor
;
import java
.lang
.reflect
.Field
;
import java
.lang
.reflect
.InvocationTargetException
;
import java
.lang
.reflect
.Method
;
public class RefTest {
public static void main(String
[] args
) throws ClassNotFoundException
, NoSuchMethodException
, IllegalAccessException
, InvocationTargetException
, InstantiationException
, CloneNotSupportedException
, IOException
, NoSuchFieldException
{
Student student0
=new Student();
student0
.setName("lwf");
student0
.setAge(18);
student0
.setClassName("class 1");
System
.out
.println(student0
);
Class
c=Class
.forName("com.lwf.Student");
Constructor
[] constructors
= c
.getDeclaredConstructors();
for(Constructor c1
: constructors
){
System
.out
.println(c1
);
}
Field
[] declaredFields
= c
.getDeclaredFields();
System
.out
.println("属性");
for(Field field
:declaredFields
){
System
.out
.println(field
.getName()+","+field
.getType());
}
Field field
= c
.getDeclaredField("name");
field
.setAccessible(true);
field
.set(student0
, "罗卫飞");
System
.out
.println(student0
);
Method method
=c
.getMethod("getName");
System
.out
.println(method
.invoke(student0
));
Student student1
= (Student
)c
.getConstructor(String
.class,Integer
.class,String
.class).newInstance("lwf",18,"一班");
Student student
= (Student
)c
.getConstructor().newInstance();
System
.out
.println(student
);
System
.out
.println(student1
);
Student student2
=(Student
)student1
.clone();
System
.out
.println(student2
);
ObjectOutputStream outputStream
= new ObjectOutputStream(new FileOutputStream("1.txt"));
outputStream
.writeObject(student
);
ObjectInputStream obj
=new ObjectInputStream(new FileInputStream("1.txt"));
Student object
=(Student
) obj
.readObject();
System
.out
.println(object
);
}
}
构造器 :
//反射获取对象
Student student1= (Student)c.getConstructor(String.class,Integer.class,String.class).newInstance("lwf",18,"一班");
Student student= (Student)c.getConstructor().newInstance();
获取属性并赋值
//修改访问权限,将私有属性直接修改值
Field field = c.getDeclaredField("name");//从所有属性中找;getField从public修饰属性中找属性
field.setAccessible(true);
field.set(student0, "罗卫飞");
System.out.println(student0);
获取方法并执行 Method对象调用invoke(实例,方法参数列表)
//调用方法
Method method=c.getMethod("getName");
System.out.println(method.invoke(student0));
联系:对象的创建
//new对象
Student student0=new Student();
//反射获取对象
Student student1= (Student)c.getConstructor(String.class,Integer.class,String.class).newInstance("lwf",18,"一班");
Student student= (Student)c.getConstructor().newInstance();
System.out.println(student);
System.out.println(student1);
//克隆对象 继承Coneable接口
Student student2=(Student)student1.clone();
System.out.println(student2);
//序列化获取对象
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("1.txt"));
outputStream.writeObject(student);
ObjectInputStream obj=new ObjectInputStream(new FileInputStream("1.txt"));
Student object =(Student) obj.readObject();