反射机制

1.反射机制有什么用?  

  通过java语言反射机制可以操作字节码文件。

  优点类似黑客,可以读和改写字节码文件

2.反射机制相关类都在java.lang.reflect.*;

3.反射机制相关重要类

  java.lang.Class代表i字节码文件。

  java.lang.reflect.Method代表字节码中方法字节码

  java.lang.reflect.Constructor代表字节码中构造方法字节码

  java.lang.reflect.Field代表字节码中成员变量字节码(静态变量和实例变量)

4.获取字节码的三种方式:

  1.Class c=Class.forName("完整类名带包名")
  2.Class c1=对象.getClass();
  3.Class c2=任何类型.class;
package Reflect;
public class ReflectText01 {
    //要操作一个字节码首先要找到这个类的字节码,怎么获取java.long.Class实例?
    //    三种方式
    //1.Class c=Class.forName("完整类名带包名")
    //2.Class c1=对象.getClass();
    //3.Class c2=任何类型.class;
    public static void main(String[] args) {
        /*Class.forName()
            1.静态方法
            2.方法的参数是一个字符串
            3.完整类名必须带有包名。java.long包也不能忽略。
         */
      java中每个对象里都有getClass()方法
Class c1=null; Class c2=null; try { c1=Class.forName("完整类名带包名"); int []a=new int[1]; c2=a.getClass(); Class c3=int.class; } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } } 

指向是都是方法区,存储都都是地址,‘==’

 

5.1 Object o=a.newInstance();方法

 

 5.反射机制可以创建对象(重要)

那我们为什么不直接new一个对象呢?显然,它一定有存在的道理,它有着很强的耦合性,极大提高了程序的灵活度,遵循ocp原则!---框架

package Reflect;
import java.io.FileReader;
import java.util.Properties;
public class ReflectText02 {
    public static void main(String[] args) throws Exception{
        /*通过IO流读取.properties文件
        优点:通过文件存储,不需要再更改代码,提高程序耦合性
        */
        FileReader reader=new FileReader("D:\\java\\javatext\\text.txt");
        //创建属性类对象Map
        Properties p=new Properties();//(String key,String value)key=value
        //加载reader
        p.load(reader);
        //关闭
        reader.close();
        //通过key获取value
        String s=p.getProperty("className");
        //通过反射机制实例化对象
        Class a=Class.forName(s);
        Object o=a.newInstance();
        System.out.println(o);
    }
}

配置文件如下:

 顺便回顾一下配置文件注意事项:

 

静态代码块在类加载时执行!!!!

package Reflect;
public class User {
//静态代码块
static { System.out.println("这是一个静态代码块!!!!!!!!!!"); } User(){ System.out.println("这是一个user类!!!!!!!!!"); } public static void main(String[] args) { try { Class.forName("Reflect.User");//字节码文件 } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } }

6.聊聊路径:(重要)

 

补充一下:想要找到绝对路径必须将文件放在src类路径目录下,必须是直接的,中间不能有目录包含。不然找不到..

伪代码:

 这种方式获取的绝对路径是通用的

 这样写,以后文件在类路径下也就是src下的文件都可以被找到,即使更换了路径,即使不用windows系统,它依然可以被找到,很牛逼,提高了程序的耦合性

第二种写法:

第三种:(推荐)

7.使用资源绑定器

资源绑定器:只能绑定xxx.properties文件,并且这个文件必须在类路径下。并且在写路径的时候,路径后面的扩展名不能写、

package Reflect;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.ResourceBundle;

public class User {
    public static void main(String[] args) {
            //资源绑定器
            ResourceBundle r=ResourceBundle.getBundle("text02");//不能带.properties后缀!!!!!!!!!!
            String s1=r.getString("className");
            System.out.println(s1);
    }
}

ps:还是得在src目录下面

8.双亲委派机制(了解)

//启动是父,扩展是母。这样避免了有人篡改数据。

 

9.1反射--Filed(属性)类

常用方法:

Class a=Class.forName("Student");
String s2=a.getName();//获取完整类名
String f1=a.getSimpleName();//获取简类名
Field[] fields=a.getFields();////Fields只能获取权限为公共的属性
Field[] fields1=a.getDeclaredFields();//DeclaredFields这个是获取所有属性
Field f=fields[0];//第一个属性
String fName=f.getName();//得到属性名
Class aClass=f.getType();//获取类型名
int t=f.getModifiers();
String sm=Modifier.toString(t);//能将int转为String
Modifier(修饰符)中toString能将int转换为String

 

package Reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
//Field(属性)
public class ReflectText03 {
    public static void main(String[] args) throws Exception{
        //获取类
        Class a=Class.forName("Student");
        String s2=a.getName();//获取完整类名
        String f1=a.getSimpleName();//获取简类名
        Field[] fields=a.getFields();////Fields只能获取权限为公共的属性
        Field[] fields1=a.getDeclaredFields();//DeclaredFields这个是获取所有属性
        Field f=fields[0];//第一个属性
        String fName=f.getName();//得到属性名
        Class aClass=f.getType();//获取类型名
        int t=f.getModifiers();//返回的是数字,每个修饰符都有数字代号!!
        String sm=Modifier.toString(t);//能将int转为String
        System.out.println(s2);
    }
}

1.通过反射机制访问对象属性

 .set(对象,修改值)

 9.2反射--Method(方法)类(重要!!)

2.1可变长参数(重点)

语法:类型...args

1,(参数随便取,3个点)

2,可变长参数在参数列表中只能存在一个并且要放到最后

3,可变长参数可以当一个数组(能用.lenth)

public static void m(int...args){}

 

 2.2.Method类

    常用方法:

  Modifier.toString(c1.getModifiers()//获取修饰符(记得转tostring)
  m.getReturnType().getSimpleName();//获取返回值类型的简类名
  m.getName();//获取名字
   Class[] pt=m.getParameterTypes();//获取数据类型
    //获取参数
  for (Class c:pt) {System.out.println(c.getSimpleName();}
2.3通过反射机制调用对象属性并修改(主要使用到了属性的set()方法)
package Reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ArgsText {
    public static void main(String[] args) throws Exception{
        Class c1=Class.forName("Reflect.User");
        Method[] a=c1.getDeclaredMethods();
        for (Method m:a
             ) {
            System.out.println(Modifier.toString(c1.getModifiers()));//获取修饰符(记得转tostring)
            System.out.println(m.getReturnType().getSimpleName());//获取返回值类型的简类名
            System.out.println(m.getName());//获取名字
            Class[] pt=m.getParameterTypes();//获取数据类型
            //获取参数
            for (Class c:pt
                 ) {
                System.out.println(c.getSimpleName());
            }
        }
    }
    public static void m(int...args){
        System.out.println("m方法执行了!!!");
    }
}

2.4通过反射机制调用方法(获取返回值)

类、对象、方法【实参】、返回值package Reflect;

import java.lang.reflect.Method;
public class MethodText01 {
    public static void main(String[] args) throws Exception{
        Class aClass=Class.forName("Student");//获取类
        Object obj=aClass.newInstance();//获取对象
        //四要素:
        /*
        Method方法
        obj对象
        “lengbo”,“123” 实参
        retvalue 返回值
         */
   
                            //(方法名,形参类型.class......【可以是n个】)
        Method method=aClass.getDeclaredMethod("logn",String.class,String.class);//获取方法、实参
        Object o=method.invoke(obj,"lengbo","wjn12345");//获取返回值(获取对象,实参列表...【可以n个】)
        System.out.println(o);
    }
}

9.3反射--Constructer类(构造方法)

还是:类,对象,构造方法(构造方法也是可以n个参数)

package Reflect;
import java.lang.reflect.Constructor;
public class ReflectConstructertext01 {
    public static void main(String[] args) throws  Exception{
        Class c=Class.forName("Student");//获取类
        Object obj=c.newInstance();//获取对象
        System.out.println(obj);
        Constructor constructor=c.getDeclaredConstructor();//获取无参构造方法
        Object o1=constructor.newInstance();//调用无参时的方法
        System.out.println(o1);
        Constructor constructor1=c.getDeclaredConstructor(int.class,String.class);//获取有参构造方法
        Object o2=constructor1.newInstance(10,"lengbo");//调用有参时方法
        System.out.println(o2);

    }
}

9.4反射--获取反射对象的实现的接口与继承的父类

一样,类,对象,接口,super(父类)

package Reflect;

public class extendsReflecttext01 {
    public static void main(String[] args) throws  Exception{
        Class c=Class.forName("java.lang.String");
        Class superc=c.getSuperclass();//获取String的父类
        System.out.println(superc.getSimpleName());
        Class []interfaces=c.getInterfaces();//获取String的实现接口
        for (Class i:
             interfaces) {
            System.out.println(i.getName());

        }
    }

}

反射到这里就结束了,你很厉害,加油!

posted @ 2023-05-19 23:41  22软工冷薄  阅读(14)  评论(0编辑  收藏  举报