目录
一、反射机制的作用:
- 通过java语言中的反射机制可以操作字节码文件。
- 通过java语言中的反射机制可以操作class文件。
- 可以让程序变得更加灵活。
二、反射机制相关类:
- java.lang.Class代表整个字节码
- java.lang.reflect.Method代表字节码中的方法字节码
- java.lang.reflect.Constructor代表字节码中的构造方法字节码
- java.lang.reflect.Field代表字节码中的属性字节码
public class Test{
//Field
int no;
//Constructor
public Test(){
}
//Method
public void dosome(){
}
}
三、获取Class的方法:
- Class.forName(“完整类名”);
(1)静态方法。
(2)方法的参数是一个字符串。
(3)字符串去要填一个完整的类名。
(4)完整类名必须带有包名。
例如:Class c1 = Class.forName(“java.lang.String”); - 对象.getClass();
(1)Object类中的方法,java中任何对象都有这个方法。
例如:Class c1 = s.getClass(); - 数据类型.class;
(1)任何类型都有class属性。
例如:Class c1 = int.class;
四、反射机制动态实例化对象:
1. 反射机制实例化对象:
public class Test{
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("java.lang.String");//通过反射机制获取Class
Object obj = c.newInstance();//通过Class实例化对象
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
/*等同于*/
String s = new String();
}
}
注意:newInstance()方法是通过调用c的无参数构造方法实例化对象,必须保证无参数构造方法存在。如果只定义有参数构造方法,无参数构造方法就没了,这种方法创建对象时就会报错。
2. 通过读属性文件实例化对象:
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class Test{
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
FileReader fr = new FileReader("javase/src/myfile");//通过IO流读取文件
Properties pro = new Properties();//IO和Properties联合使用(文章)
pro.load(fr);
fr.close();
String s = pro.getProperty("class");
Class c = Class.forName(s);
Object obj = c.newInstance();
System.out.println(obj);
}
}
不需要改变java代码,通过修改myfile文件内容就可以创建不同对象。
框架思想。
五、如何不实例化对象,只执行类中的静态代码块:
public class Test{
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("Test1");
}
}
class Test1{//右键类名,copy->copy reference复制类的完整类名
static{
System.out.println("静态代码块执行");
}
}
六、如何获取类路径src下文件的绝对路径:重点
String path = Thread.currentThread().getContextClassLoader().getResource("myfile").getPath();
name变量从类的根路径src下作为起点。
适合各种操作系统,Linux也适用。
七、如何获取类路径src下文件的流:重点
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("myfile");
八、资源绑定器:重点
用于根据key值获取属性配置文件中value值。
import java.util.ResourceBundle;
public class Test{
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("myfile");
String s = bundle.getString("name");
System.out.println(s);
}
}
只能用于.properties文件且文件必须位于类路径下。
九、获取Field:重点
- 获取属性类型
- 获取属性名
- 获取属性修饰符
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Test{
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("Test1");//获取类
//Field field[] = c.getFields();//获取所有public属性,返回Field数组
Field field[] = c.getDeclaredFields();//获取所有属性,返回Field 数组
for(Field fd:field){
//获取属性类型
Class fieldType = fd.getType();//返回Class类型
String fType = fieldType.getSimpleName();
System.out.println(fType);
//获取属性名字
String fName = fd.getName();//返回String类型
System.out.println(fName);
//获取属性修饰符
int fieldModifiers = fd.getModifiers();//返回int类型
String fModifiers = Modifier.toString(fieldModifiers);
System.out.println(fModifiers);
}
}
}
class Test1{
public int a;
private double b;
protected String c;
}
十、反射机制给属性赋值:重点
import java.lang.reflect.Field;
public class Test{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class TestClass = Class.forName("TestClass");//创建类
Object test = TestClass.newInstance();//创建对象
Field a1 = TestClass.getDeclaredField("a");//根据属性名获取属性
a1.set(test,123);//给test对象的a1属性赋值123,不能访问私有属性
a1.get(test);//获取test对象的a1属性的值
Field a2 = TestClass.getDeclaredField("is");//根据属性名获取属性
a2.setAccessible(true);//打破封装,使得该私有属性可以访问
a2.set(test,false);//给test对象的a1属性赋值123,不能访问私有属性
a2.get(test);//获取test对象的a1属性的值
}
}
class TestClass {
public int a;
private boolean is;
protected double b;
}
十一、可变长度参数:
public class Test{
public static void m(int ...args){//可变长参数语法,可变长参数只能有一个,必须出现在参数最后一个位置,可看做数组
for (int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
m();
m(12,13);
m(1,2,4,0);
}
}
十二、获取Method:
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class c = Class.forName("TestClass");//创建类
Method[] methods = c.getDeclaredMethods();//获取方法
for (Method method :methods){
//获取修饰符
int m = method.getModifiers();
String s1 = Modifier.toString(m);
//获取返回值类型
Class n = method.getReturnType();
String s2 = n.getSimpleName();
//获取方法名
String s3 = method.getName();
//获取参数类型
Class[] types = method.getParameterTypes();
for(Class parameter:types){
String s4 = parameter.getSimpleName();
}
}
}
}
class TestClass{
public void m1() {
}
}
十三、通过反射机制调用对象的方法:重点
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* invoke方法的使用:。
* 实际上invoke方法的使用,和我们常见的有所区别。
* 我们经常创建一个对象A,A对象里面的方法getA()方法,然后A.getA()
* 我们采用新的方式调用:
* (1)弄一个方法的“替身”(其实就是构建一个Method对象,让这个Method对象来代替你现在要用的方法)
* (2)然后给替身需要的对象和参数,让替身去替你调用
*/
public class Test{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
Class c = Class.forName("TestClass");//创建类
Object o = c.newInstance();//创建对象
Method method = c.getDeclaredMethod("m1",String.class,int.class);//根据c类的方法名和参数类型获取某个方法
Object returnValue = method.invoke(o,"abc",123);//调用o对象的invoke方法给method方法传入参数“abc”和123得到method方法的返回值returnValue******重点********
}
}
class TestClass{
public void m1(String a1,int a2) {
}
public void m1(String a1){
}
}
十四、通过反射机制调用构造方法:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test{
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class c = Class.forName("TestClass");//创建类
Constructor c1 = c.getDeclaredConstructor(int.class,double.class);//通过类名和参数获取构造方法
Object obj = c1.newInstance(12,10.1);//通过构造方法创建对象
Object obj1 = c.newInstance();//通过无参构造方法创建对象
}
}
class TestClass{
int a;
double b;
public TestClass(int a, double b) {
this.a = a;
this.b = b;
}
}
十五、通过反射机制获取父类和父接口:
public class Test{
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("java.lang.String");//创建类
//获取String类的父类
Class superclass = c.getSuperclass();
String s = superclass.getName();
//获取String类的所有父接口
Class[] interfaces = c.getInterfaces();
for (Class i:interfaces) {
String ss = i.getName();
}
}
}