反射

反射

1.反射可以操作Java字节码,创建对象,让程序更加灵活

2.反射相关类在java.lang.reflect.包下

3.反射相关的类有哪些呢?

java.lang.Class代表整个字节码文件,类似Java类

java.lang.reflect.Method代表Java字节码中的方法,类似类中的方法

java.lang.reflect.Constructor:代表Java字节码中的构造方法,类似类的构造方法

java.lang.reflect.Field代表字节码中的属性字节码,代表Java类中的成员变量

4.获取字节码java.lang.Class实例(注意:字节码文件加载到了方法区,只会存在一份)

(1)Class类–java.lang.Class

Class.forName(完整包名+类名)-----------------获取类的字节码文件

(2)java中的任何一个对象都有getClass方法获取它的字节码文件

对象.getClass();

(3)Class c= String.class属性获取

 Class<String> stringClass = String.class;

5.反射小案例:反射更灵活,该配置文件就可以生成不同对象

classInfo.properties

className=java.util.Date

利用反射访问:创建对象

public class test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
        FileReader fileReader = new FileReader("src/classInfo.properties");
        Properties properties = new Properties();
        properties.load(fileReader);
        fileReader.close();
        String className = properties.getProperty("className");

        Class<?> aClass = Class.forName(className);
        Date date = (Date) aClass.newInstance();
        System.out.println(date);

    }
}

6.class.forName的作用

class.forName 会导致类的加载,导致静态代码块的执行

newInstance实例化会调用对象的无参构造方法

className=User
class User{
    private int age;
    private String name;
    public User(){
        System.out.println("无参构造");
    }
    static {
        System.out.println("我是静态代码块");
    }
}
public class test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
        FileReader fileReader = new FileReader("src/classInfo.properties");
        Properties properties = new Properties();
        properties.load(fileReader);
        fileReader.close();
        String className = properties.getProperty("className");

        Class<?> aClass = Class.forName(className);
        User user = (User) aClass.newInstance();
        System.out.println(user);
    }
}
我是静态代码块
无参构造
User@16b98e56

7.src下的文件—获取文件的绝对路径

src 是类的根路径,我们获取路径,必须从类的根路径src下获取(文件不能在src外面)

参数写src下的路径com/bj/classInfo.properties(相对路径)

     //拿到一个文件的绝对路径
        String path = Thread.currentThread().getContextClassLoader().getResource("com/bj/classInfo.properties").getPath();
        System.out.println(path);
/D:/MyAppClass/IDEA2019/test/out/production/test/com/bj/classInfo.properties

8.反射的方法(获取属性—操作属性)

class Student{
    private int age;
    private String name;
    protected int no;
    public boolean sex;
}

getFields()获取所有public修饰的属性

        Class<?> student = Class.forName("Student");
        Field[] fields = student.getFields();
        System.out.println(fields.length);
        System.out.println(fields[0]);

结果:
1
public boolean Student.sex

getDeclaredFilelds()获取所有的属性

 Field[] declaredFields = student.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            System.out.println(declaredFields[i]);
        }

结果

private int Student.age
private java.lang.String Student.name
protected int Student.no
public boolean Student.sex

注意,declaredFields[i]数组中的每一个类型是private int Student.age这个整体

 Field[] declaredFields = student.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            System.out.println(declaredFields[i].getName()  +"   "+  declaredFields[i].getType());
        }

结果:

age   int
name   class java.lang.String
no   int
sex   boolean

获取访问修饰符getModifiers()

    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> student = Class.forName("Student");
        Field[] declaredFields = student.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            int modifiers = declaredFields[i].getModifiers();
            System.out.println(modifiers);
            System.out.println(Modifier.toString(modifiers));
        }

结果:

2
private
2
private
4
protected
1
public

我们可以看出我们的getModifiers方法返回的是int类型的整数,代表访问修饰符的代号

4是protect 2 是private 1是public 我们可以调用Modifier的静态方法将代号转为字符串

**8.反射—反编译:**强大:

 public static void main(String[] args) throws ClassNotFoundException {
        StringBuilder stringBuilder = new StringBuilder();

        Class<?> stringClass = Class.forName("java.lang.String");
        stringBuilder.append(
                Modifier.toString(stringClass.getModifiers()) +"  class  " +stringClass.getSimpleName()  +"{"
        );

        Field[] fields = stringClass.getDeclaredFields();
        for (Field field : fields) {
            stringBuilder.append("\n");
            stringBuilder.append("\t");
            stringBuilder.append(Modifier.toString(field.getModifiers()));
            stringBuilder.append("  ");
            stringBuilder.append(field.getType().getSimpleName());
            stringBuilder.append("  ");
            stringBuilder.append(field.getName());
            stringBuilder.append(";\n");
        }
        stringBuilder.append("}");
        System.out.println(stringBuilder);
    }

结果:

public final  class  String{
	private final  byte[]  value;

	private final  byte  coder;

	private  int  hash;

	private static final  long  serialVersionUID;

	static final  boolean  COMPACT_STRINGS;

	private static final  ObjectStreamField[]  serialPersistentFields;

	public static final  Comparator  CASE_INSENSITIVE_ORDER;

	static final  byte  LATIN1;

	static final  byte  UTF16;
}

9.通过反射机制访问Java对象的属性,给属性赋值

import java.lang.reflect.Field;

public class reflect4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class<?> user2 = Class.forName("User2");
        User2 user = (User2) user2.newInstance();
        Field name = user2.getDeclaredField("name");
        name.setAccessible(true);
        name.set(user,"xiaohong");
        System.out.println(user);
    }
}
class User2{
    private String name;
    private int age;

    @Override
    public String toString() {
        return "User2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
结果:User2{name='xiaohong', age=0}

注意:

当我们访问私有的属性的时候我们会发现无法进行赋值,因为有保护,我们必须打破封装,将属性设为可以访问的,我们才能进行赋值

name.setAccessible(true);
name.set(user,"xiaohong");

属性赋值: 属性.set(所属对象,值) ----------- 注意和 对象.set属性(值)的区别

我们通过类对象获取实例----------通过类对象获取到属性

        Class<?> user2 = Class.forName("User2");
        User2 user = (User2) user2.newInstance();
        Field age = user2.getDeclaredField("age");
        age.setAccessible(true);
        age.set(user,12);  

10.可变长度的参数:

可变长度的参数只能在方法的最后面,可以传入不同长度的参数,只能有一个,可以当作一个数组来看待(也可以传入一个数组作为参数)

public class reflectMethod {
    public static void main(String[] args) {
        method(12);
        method(12,154);
        method();

    }
    public  static void method(int ... args){
        for (int arg : args) {
            System.out.println(arg);
        }
    }
}

结果:

12
12
154

11.通过反射获得方法

public class reflect4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class<?> user2 = Class.forName("User2");
        Method[] methods = user2.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
            System.out.println(method.getName() + "---"+method.getReturnType().getName() + "--"+ Modifier.toString(method.getModifiers()));
            Parameter[] parameters = method.getParameters();
            for (Parameter parameter : parameters) {
                System.out.println(parameter.getName());
                System.out.println(parameter.getType().getSimpleName());
            }
        }
    }
}
class User2{
    private String name;
    private int age;
    public void method(int age,String name){
        System.out.println(this.age+"----"+this.name);
    }
}

结果:

private void User2.method(int,java.lang.String)
method—void–private
arg0
int
arg1
String

12.通过反射机制调用方法

import java.lang.reflect.*;

public class reflect4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class<?> user2 = Class.forName("User2");
        Method method = user2.getDeclaredMethod("method", int.class, String.class);
        User2 user = (User2) user2.newInstance();
        method.setAccessible(true);
        Object result = method.invoke(user, 34, "小明");
        System.out.println(user);
        System.out.println(result);
    }
}
class User2{
    private String name;
    private int age;
    private int method(int age,String name){
        System.out.println(age+ "--" +name);
        System.out.println(this.age+"----"+this.name);
        return 12;
    }
}

结果:

34–小明
0----null
User2@3d494fbf
12

重点:

(1)invoke方法调用方法执行, 格式 方法.invoke(对象,参数)

Object result = method.invoke(user, 34, “小明”);

(2)因为方法可能存在重载现象,所以我们获取方法的时候应该指定参数的类型

Method method = user2.getDeclaredMethod(“method”, int.class, String.class);

(3)私有方法,还要设置可访问

13.通过反射得到构造方法,构造方法创建对象

        Class<?> user2 = Class.forName("User2");
        Constructor<?> con = user2.getDeclaredConstructor(String.class, int.class);
        Object xioahua = con.newInstance("xioahua", 12);
        System.out.println(xioahua.toString());
    }

结果:User2{name=‘xioahua’, age=12}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值