【java】反射基础

简介: 【java】反射基础

Class类

import java.io.*;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<String> clazz = String.class;   //使用class关键字,通过类名获取
        Class<?> clazz2 = Class.forName("java.lang.String");
        //使用Class类静态方法forName(),通过包名.类名获取,注意返回值是Class<?>
        String c=new String("coleak");
        Class<?> clazz3 = c.getClass();  //通过实例对象获取
        System.out.println(clazz);
    }
}

class java.lang.String

Class类也是一个泛型类,只有第一种方法,能够直接获取到对应类型的Class对象,而以下两种方法使用了?通配符作为返回值,但是实际上都和第一个返回的是同一个对象

即:在JVM中每个类始终只存在一个Class对象,无论通过什么方法获取,都是一样的

public class Main {
    public static void main(String[] args) {
        Class<String[]> clazz = String[].class;
        System.out.println(clazz.getName());  //获取类名称(得到的是包名+类名的完整名称)
        System.out.println(clazz.getSimpleName());
        System.out.println(clazz.getTypeName());
        System.out.println(clazz.getClassLoader());   //获取它的类加载器
    }
}

Class对象与多态

import java.lang.reflect.Type;
public class Main {
    public static void main(String[] args) {
        String str = "";
        System.out.println(str.getClass());
        System.out.println(str instanceof String);
        System.out.println(str.getClass() == String.class);   //直接判断是否为这个类型
        Integer i = 10;
        System.out.println(i.getClass().asSubclass(Number.class));   //当Integer不是Number的子类时,会产生异常
        System.out.println(i.getClass().getSuperclass());
        Type type = i.getClass().getGenericSuperclass();
        //getGenericSuperclass()获取父类的原始类型
        System.out.println(type);
        System.out.println(type instanceof Class);
    }
    }

class java.lang.String

true

true

class java.lang.Integer

class java.lang.Number

class java.lang.Number

true

创建类对象

无参构造

public class Main {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException
    {
        Class<Student> clazz = Student.class;
        Student student = clazz.newInstance();
        student.test();
    }
    static class Student{
        public void test(){
            System.out.println("coleak");
        }
    }
    }

构造器

import java.lang.reflect.InvocationTargetException;
public class Main {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Student> clazz = Student.class;
        Student student = clazz.getConstructor(String.class).newInstance("coleak");
        student.test();
    }
    static class Student{
        public Student(String str){}
        public void test(){
            System.out.println("cc");
        }
    }
    }

非public权限

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Main {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Student> clazz = Student.class;
        Constructor<Student> constructor = clazz.getDeclaredConstructor(String.class);
        constructor.setAccessible(true);   //修改访问权限
        Student student = constructor.newInstance("coleak");
        student.test();
    }
    static class Student{
        private final String name;
        private Student(String str){
            this.name=str;
        }
        public void test(){
            System.out.println(name);
        }
    }
    }

调用类方法

public权限

import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("com.test.Student");
        Object instance = clazz.newInstance();   //创建出学生对象
        Method method = clazz.getMethod("test", String.class);   
        //通过方法名和形参类型获取类中的方法
        method.invoke(instance, "coleak");   
        //通过Method对象的invoke方法来调用方法
    }
    }

非public权限

package com.test;
public class Student {
    private void test(String str){
        System.out.println("coleak"+str);
    }
}
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("com.test.Student");
        Object instance = clazz.newInstance();   //创建出学生对象
        Method method = clazz.getDeclaredMethod("test", String.class);   
        //通过方法名和形参类型获取类中的方法
        method.setAccessible(true);
        method.invoke(instance, "coleak");   //通过Method对象的invoke方法来调用方法
    }
    }
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("com.test.Student");
        Method method = clazz.getDeclaredMethod("test", String.class);   //通过方法名和形参类型获取类中的方法
        System.out.println(method.getName());   //获取方法名称
        System.out.println(method.getReturnType());   //获取返回值类型
    }
}
//方法的参数为可变参数时
Method method = clazz.getDeclaredMethod("test", String[].class);

可以直接通过Method对象来获取这些信息

修改类的属性

public权限

package com.test;
public class Student {
    public int i;
    public void test(){
        System.out.println("coleak"+i);
    }
}
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("com.test.Student");
        Object instance = clazz.newInstance();
        Field field = clazz.getField("i");   //获取类的成员字段i
        field.set(instance, 100);   //将类实例instance的成员字段i设置为100
        Method method = clazz.getMethod("test");
        method.invoke(instance);
    }
}

非public权限

import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Main {
    public static void main(String[] args) throws ReflectiveOperationException {
        Class<?> clazz = Class.forName("com.test.Student");
        Object instance = clazz.newInstance();
        Field field = clazz.getDeclaredField("i");   //获取类的成员字段i
        field.setAccessible(true);
        field.set(instance, 100);   //将类实例instance的成员字段i设置为100
        Method method = clazz.getMethod("test");
        method.invoke(instance);
    }
}

类加载器

public class Main {
    public static void main(String[] args) {
        System.out.println(Main.class.getClassLoader());   //查看当前类的类加载器
        System.out.println(Main.class.getClassLoader().getParent());  //父加载器
        System.out.println(Main.class.getClassLoader().getParent().getParent());  //爷爷加载器
        System.out.println(String.class.getClassLoader());   //String类的加载器
    }
}

jdk.internal.loader.ClassLoadersA p p C l a s s L o a d e r @ 2437 c 6 d c j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s AppClassLoader@2437c6dc jdk.internal.loader.ClassLoadersAppClassLoader@2437c6dcjdk.internal.loader.ClassLoadersPlatformClassLoader@49e4cb85

null

null

BootstarpClassLoader是C++编写的,我们在Java中是获取不到的

目录
相关文章
|
23天前
|
安全 Java 测试技术
day26:Java零基础 - 反射
【7月更文挑战第26天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
23 5
|
1月前
|
IDE Java 测试技术
Java进阶之反射
【7月更文挑战第14天】Java反射机制允许在运行时动态获取类信息、创建对象及调用其方法。它基于`Class`类,让我们能访问类的属性、方法、构造器。例如,通过`Class.forName()`加载类,`Class.newInstance()`创建对象,`Method.invoke()`执行方法。反射广泛应用于动态代理、单元测试、序列化及框架中,提供灵活性但牺牲了性能,且可破坏封装性。IDE的代码补全也是反射的应用之一。在使用时需谨慎,避免对私有成员的不当访问。
23 1
|
1月前
|
Java 程序员 测试技术
解析Java中的反射机制及其应用场景
解析Java中的反射机制及其应用场景
|
1月前
|
开发框架 Java Android开发
Java中的类反射与动态代理详解
Java中的类反射与动态代理详解
|
1月前
|
缓存 Java 测试技术
Java中的反射机制及其应用场景
Java中的反射机制及其应用场景
|
1月前
|
Java
Java中的反射与动态代理机制详解
Java中的反射与动态代理机制详解
|
1月前
|
存储 安全 Java
Java中的反射机制及其应用场景详解
Java中的反射机制及其应用场景详解
|
1月前
|
安全 Java
JAVA反射:如何在运行时“创造”你的对象?
【7月更文挑战第1天】Java反射机制允许在运行时动态创建对象,常用于插件系统和框架开发。与`new`关键字相比,反射提供更大的灵活性,能根据条件决定对象类型,但牺牲了性能和代码可读性。示例展示了如何通过`Class.forName()`和`Constructor.newInstance()`创建对象,过程中需处理异常。反射还可访问私有成员,增加安全风险,故使用时需谨慎。
22 2
|
1月前
|
安全 Java 测试技术
Java中的反射与元编程技术探秘
Java中的反射与元编程技术探秘
|
1月前
|
Java API
Java注解与反射机制
Java注解与反射概述: - 注解用于元数据,包括元注解`@Target`, `@Retention`, `@Documented`, `@Inherited`。 - 自定义注解用于自定义行为标记,参考[链接]例化后通过`getClass()`获取类信息。 - 主要API涉及类的多种获取方式,如`对象.getClass()`, `类名.class`, `Class.forName()`和内置类型`TYPE`。 - 应用场景包括动态创建对象,获取泛型和注解信息以及分析运行时结构。