Loading

Java基础-注解与反射

注解

  • Annotation是从JDK5.0开始引入的新技术.
  • Annotation的作用:不是程序本身,可以对程序作出解释.(这一点和注释(comment)没什么区别)
  • 可以被其他程序(比如:编译器等)读取.
  • Annotation的格式:
    注解是以"@注释名"在代码中存在的,还可以添加一些参数值﹐例如:@SuppressWarnings(value="unchecked").
  • Annotation在哪里使用?
    可以附加在package , class , method , field等上面﹐相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

内置注解

  • @Override:定义在java.lang.Override中,此注释只适用于修辞方法﹐表示一个方法声明打算重写超类中的另一个方法声明.
  • @Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法﹐属性﹐类,表示不鼓励程序员使用这样的元素﹐通常是因为它很危险或者存在更好的选择.
  • @suppressWarnings :定义在java.lang.SuppressWarnings中,用来抑制编译时的警告信息.
  • 与前两个注释有所不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好了的,我们选择性的使用就好了﹒
    √@SuppressWarnings("all")
    √ SuppressWarnings("unchecked")
    √@SuppressWarnings(value={"unchecked" ,"deprecation"})√等等.....
package annotation.demo1;

import java.util.ArrayList;
import java.util.List;

public class Test {
    //重写的注解
    @Override
    public String toString() {
        return super.toString();
    }

    //Deprecated 不推荐使用,但可以使用
    @Deprecated
    public void dep(){
        System.out.println("Deprecated");
    }

    //SuppressWarnings 镇压警告 需要有参数
    @SuppressWarnings("all")
    public void sws(){
        List l = new ArrayList();
    }

}

元注解

元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明.

这些类型和它们所支持的类在java.lang.annotation包中可以找到.

  • Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
  • @Retention:表示需要在什么级别保存该注释信息﹐用于描述注解的生命周期 (SOURCE< CLASS < RUNTIME)
  • @Document:说明该注解将被包含在javadoc中
  • @Inherited:说明子类可以继承父类中的该注解
package annotation.demo1;

import java.lang.annotation.*;

public class Test2 {
    @MyAnnotation
    public void test(){

    }
}

//定义一个注解
//Target表示注解可以用在哪些地方
@Target(value= ElementType.METHOD)
@interface MyAnnotation{

}

//Retention 表示注解在什么地方有效
//RUNTIME>CLASS>SOURCES
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation2{

}

//Documented 表示注解是否生成在JAVA doc中
@Documented
@interface MyAnnotation3{
    
}

//Inherited 子类可以继承父类的注解
@Inherited
@interface MyAnnotation4{
    
}

自定义注解

使用@interface自定义注解时﹐自动继承了java.lang.annotation.Annotation接口

  • @interface用来声明一个注解﹐格式: public @interface 注解名
  • 其中的每一个方法实际上是声明了一个配置参数.
  • 方法的名称就是参数的名称.
  • 返回值类型就是参数的类型(返回值只能是基本类型,Class , String , enum ).√可以通过default来声明参数的默认值
  • 如果只有一个参数成员﹐一般参数名为value
  • 注解元素必须要有值﹐我们定义注解元素时﹐经常使用空字符串,0作为默认值.
package annotation.demo1;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class Test3 {
    @MyAnno(name = "Test")
    public void test(){
    }

    @MyAnno2("test")
    public void test2(){
    }
}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno{
    String name() default  "";
    int age() default 0;
    int id() default -1;
    String[] school() default {"北京大学", "清华大学"};

}

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno2{
    String value();
}

概念

动态语言

是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
主要动态语言:Object-C、C#、JavaScript、PHP、Python等。

静态语言

与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++.
Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制获得类似动态语言的特性。Java的动态性让编程的时候更加灵活。

Reflection(反射)是Java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

Class c = Class.forName("java.lang.String")

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射

image-20210810160524700

功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理

优缺点

优点:可以实现动态创建对象和编译,体现出很大的灵活性。

确定:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作。

反射类

package reflection.demo1;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        Class c1 = Class.forName("reflection.demo1.User");
        System.out.println(c1);

        //一个类在内存中只有一个class
        //一个内被加载后,整个类都封装在Class中
        Class c2 = Class.forName("reflection.demo1.User");
        System.out.println(c1.hashCode() + " " + c2.hashCode());

    }
}

//实体类:pojo,entity
class User{
    private String name;
    private int id;
    private int age;

    public User(){
    }

    public User(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
/**
class reflection.demo1.User
381259350 381259350
**/

Class类

对象照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个结构(class/interface/enum/annotation/primitive type/void/[])的有关信息。

  • Class 本身也是一个类
  • Class对象只能由系统建立对象
  • 一个加载的类在JVM中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个Class实例所生成
  • 通过Class可以完整地得到一个类中的所有被加载的结构
  • Class类是Reflection的根源,针对任何你想动态加载、运行的类,唯有先获得相应的Class对象

常用方法

  • static ClassforName(String name) 返回指定类名name的Class对象
  • Object newlnstance() 调用缺省构造函数,返回Class对象的一个实例
  • getName() 返回此Class对象所表示的实体(类,接口,数组或void)的名称。
  • Class getSuperClass() 返回当前Class对象的父类的Class对象
  • Class[ getinterfaces() 获取当前Class对象的接口
  • ClassLoader getClassLoader() 返回该类的类加载器
  • Constructor[]getConstructors() 返回一个包含某些Constructor对象的数组
  • Method getMothed(String name,Class.. T) 返回一个Method对象,此对象的形参类型为paramType
  • Field[] getDeclaredFields() 返回Field对象的一个数组
package reflection.demo1;

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person p = new Student();
        System.out.println(p.getName());

        //方法1:通过对象获得
        Class c1 = p.getClass();
        System.out.println(c1 + "/" + c1.hashCode());

        //方法2:通过forName获得
        Class c2 = Class.forName("reflection.demo1.Student");
        System.out.println(c2 + "/" +c2.hashCode());

        //方法3:通过类名.class获得
        Class c3 = Student.class;
        System.out.println(c3 + "/" +c3.hashCode());

        //方法4:基本内置类型的包装都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4 + "/" +c4.hashCode());

        //获得父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5 + "/" +c5.hashCode());
    }
}

class Person{
    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" + "name=" + name + "}";
    }
}

class Student extends Person{
    public Student(){
        setName("学生");
    }
}

class Teacher extends Person{
    public Teacher(){
        setName("老师");
    }
}

所有类型的class类

package reflection.demo1;

import java.lang.annotation.ElementType;

public class Test4 {
    public static void main(String[] args) {
        Class c1 = Object.class;      //类
        Class c2 = Comparable.class;  //接口
        Class c3 = String[].class;    //一维数组 
        Class c4 = int[][].class;     //二维数组
        Class c5 = Override.class;    //注解
        Class c6 = ElementType.class; //枚举
        Class c7 = Integer.class;     //基本数据类型
        Class c8 = void.class;        
        Class c9 = Class.class;

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);

        //只要元素的类型和维度一样,就属于同一个Class
        int[] a = new int[10];
        int[] b = new int[100];
        int[][] c = new int[10][10];
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
        System.out.println(c.getClass().hashCode());
    }
}
/**
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
381259350
381259350
2129789493
**/

Java内存

  • 存放new的对象和数组 可以被所有线程共享,不会存放别的对象引用
  • 存放基本的变量类型(会包含这个基本的具体数值) 引用对象的变量(会存放这个引用在堆里面的具体地址)
  • 方法区 可包含所有的线程共享 包含了所有的class和static变量

类加载

image-20210810210754659

  • 类的加载
    就是指将class文件读入内存,并为之创建一个java.lang.Class对象任何类被使用时,系统都会为之建立一个java.lang.Class对象
  • 类的连接
    验证阶段:用于检验被加载的类是否有正确的内部结构,并和其他类协调一致 准备阶段:负责为类的类变量分配内存,并设置默认初始化值
    解析阶段:将类的二进制数据中的符号引用替换为直接引用
  • 类的初始化
    在该阶段,主要就是对类变量讲行初始化

类的初始化步骤

  • 假如类还未被加载和连接,则程序先加载并连接该类
  • 假如该类的直接父类还未被初始化,则先初始化其直接父类
  • 假如类中有初始化语句,则系统依次执行这些初始化语句

类的初始化时机

  • 创建类的实例调用类的类方法
  • 访问类或者接口的类变量,或者为该类变量赋值
  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类

类加载器的作用

将.class文件加载到内存中,并为之生成对应的java.lang.Class对象

JVM的类加载机制

  • 全盘负责;就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入
  • 父类委托:就是当一个类加载器负责加载某个Class时,先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类
  • 缓存机制:保证所有加载过的Class都会被缓存,当程序需要使用某个Class对象时,类加载器先从缓存区中搜索该Class,只有当缓存区中术存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存储到缓存区

类加载器

ClassLoader:负责加载类的对象

内置加载器

  • Bootstrap class loader: 它是虚拟机的内置类加载器,通常表示为null,并且没有父null
  • Platform class loader: 平台类加载器可以看到所有平台类,平台类包括由平台类加载器或其祖先定义的JavaSE平台API,其实现类和JDK特定的运行时类
  • System class loader: 它也被称为应用程序类加载器,与平台类加载器不同。系统类加载器通常用于定义应用程序类路径,模块路径和JDK特定工具上的类

类加载器的继承关系:System的父加载器为Platform,而Platform的父加载器为Bootstrap

方法

  • static ClassLoader getSystemClassLoader():返回用于委派的系统类加载器
  • ClassLoader getParent():返回父类加载器进行委派
package reflection.demo2;

public class Test {
    public static void main(String[] args) {
        ClassLoader c = ClassLoader.getSystemClassLoader();
        System.out.println(c);

        ClassLoader c2 = c.getParent();
        System.out.println(c2);

        ClassLoader c3 = c2.getParent();
        System.out.println(c3);
    }
}
/**
jdk.internal.loader.ClassLoaders$AppClassLoader@2f0e140b
jdk.internal.loader.ClassLoaders$PlatformClassLoader@16b98e56
null
**/

反射

Java反射机制:是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展

Student

package reflection.demo2;

public class Student {
    private String name;
    int age;
    public String address;

    public Student() {
    }

    private Student(String name){
        this.name = name;
    }

    Student(String name, int age){
        this.name = name;
        this.age = age;
    }

    public Student(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    private void function(){
        System.out.println("function");
    }

    public void method1(){
        System.out.println("method");
    }

    public void method2(String s){
        System.out.println("method:"+s);
    }

    public String method3(String s, int i){
        return s + "/" + i;
    }

    @Override
    public String toString() {
        return "Student{\'" + name + "\', \'" + age + "\', \'" + address +"\'}";
    }
}

获取构造方法

  • Constructor<?>[] getConstructors(): 返回所有公共构造方法对象的数组
  • Constructor<?>[] getDeclaredConstructors(): 返回所有构造方法对象的数组
  • Constructor<T> getConstructor(Class<?>... parameterTypes): 返回单个公共构造方法对象
  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes): 返回单个构造方法对象
package reflection.demo3;

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("reflection.demo2.Student");

        //Constructor<?>[] getConstructors()
        //返回Class包含Constructors 对象的数组  只能拿到公共的方法
        Constructor[] cons = c.getConstructors();
        for (Constructor con:cons) {
            System.out.println(con);
        }
        System.out.println("--------------------------------");

        //Constructor<?>[] getDeclaredConstructors()
        //返回Class声明的所有构造函数的Constructors 对象的数组
        Constructor[] dcons = c.getDeclaredConstructors();
        for (Constructor dcon:dcons) {
            System.out.println(dcon);
        }
        System.out.println("--------------------------------");

        //Constructor<T> getConstructor (class<?>... parameterTypes)
        //返回一个Constructor对象,该对象反映由该cLass对象表示的类的指定公共构造函数
        //Constructor<T> getDeclaredConstructor (class<?>... parameterTypes)
        //返回一个Constructor对象,该对象反映由该cLass对象表示的类的或接口的构造函数
        //参数:你要获取的构造方法的参数的个数和数据类型对应的字节码文件对象

        Constructor con1 = c.getConstructor();

        //newInstance (Object... initargs)
        //使用由此constructor对象表示的构造函数,使用指定的初始参数来创建和初始化构造函数的声明类的新实例
        Object obj = con1.newInstance();
        System.out.println(obj);
    }

}
/**
public reflection.demo2.Student(java.lang.String,int,java.lang.String)
public reflection.demo2.Student()
--------------------------------
public reflection.demo2.Student(java.lang.String,int,java.lang.String)
reflection.demo2.Student(java.lang.String,int)
private reflection.demo2.Student(java.lang.String)
public reflection.demo2.Student()
--------------------------------
Student{null'0'null}
**/

test1

练习1:通过反射实现如下操作
Student s = new Student("Bob",18,"BeiJing"); System.out.println(s);

package reflection.demo3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("reflection.demo2.Student");

        //public Student(String name, int age, String address)
        Constructor con = c.getConstructor(String.class, int.class, String.class);
        Object obj = con.newInstance("Bob", 18, "BeiJing");
        System.out.println(obj);
    }
}

/**
Student{'Bob', '18', 'BeiJing'}
**/

test2

练习1:通过反射实现如下操作 Student s = new Student("Bob");System.out.println(s);

package reflection.demo3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("reflection.demo2.Student");

        //private Student(String name)
        Constructor con = c.getDeclaredConstructor(String.class);

        //对私有构造方法进行构造(暴力反射)
        /** void setAccessible(boolen flag)
        值为true表示反射对象应该在使用Java语言访问控制 时抑制检查。
        值为false表示反射对象应该在使用Java语言访问控制时执行检查,并在类描述中指出变体。
         **/
        con.setAccessible(true);
        Object obj = con.newInstance("Bob");
        System.out.println(obj);

    }
}
/**
Student{'Bob', '0', 'null'}
**/

获取成员变量

  • Field[] getFields(): 返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields(): 返回所有成员变量对象的数组
  • Field getField(String name): 返回单个公共成员变量对象
  • Field getDeclaredField(String name): 返回单个成员变量对象
package reflection.demo4;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("reflection.demo2.Student");

        //Field[] getFields()返回一个包含Field对象的数组,Field对象反映由该cLass对象表示的类或接口的所有可访问的公共变量
        Field[] fields = c.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("----------------------------------------------");

        //Field[] getDeclaredFields()返回一个 FieLd对象的数组,反映了由该class对象表示的类或接口声明的所有字段
        Field[] fields2 =  c.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
        System.out.println("----------------------------------------------");

        //Field getField (String name)返回一个Field对象,该对象反映由该CLass对象表示的类或接口的指定公共成员字段
        Field addressField = c.getField("address");
        System.out.println(addressField);
        System.out.println("----------------------------------------------");

        //Field getDeclaredField (String name)返回一个Field对象,该对象反映由该cLass对象表示的类或接口的指定声明字段
        Field nameField = c.getDeclaredField("name");
        System.out.println(nameField);
        System.out.println("----------------------------------------------");

        //获取无参构造方法对象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        //void set(object obj,object value)将指定的对象参数中由此Field对象表示的字段设置为指定的新值
        addressField.set(obj, "Beijing");  //给object的成员变量addressField赋值
        System.out.println(obj);
    }
}

/**
public java.lang.String reflection.demo2.Student.address
----------------------------------------------
private java.lang.String reflection.demo2.Student.name
int reflection.demo2.Student.age
public java.lang.String reflection.demo2.Student.address
----------------------------------------------
public java.lang.String reflection.demo2.Student.address
----------------------------------------------
private java.lang.String reflection.demo2.Student.name
----------------------------------------------
Student{'null', '0', 'Beijing'}
**/

Field类中用于给成员变量赋值的方法
void set(Object obj, Object value): 给obj对象的成员变量赋值为value

test1

练习:通过反射实现如下操作
student s = new Student();
s.name ="Bob";
s.age = 18;
s.address =“Beijing";
System.out.println(s);
package reflection.demo4;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class c = Class.forName("reflection.demo2.Student");

        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        //操作私有的成员变量
        Field nameField = c.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(obj, "Bob");
        System.out.println(obj);

        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj, 18);
        System.out.println(obj);

        Field addressField = c.getField("address");
        addressField.set(obj, "Beijing");
        System.out.println(obj);
    }
}

获取成员方法

Class类中用于获取成员方法的方法

  • Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
  • Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
  • Method getMethod(String name, Class<?>... parameterTypes): 返回单个公共成员方法对象
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes): 返回单个成员方法对象
package reflection.demo5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("reflection.demo2.Student");

        //Method[] getMethods()返回一个包含方法对象的数组
        //方法对象反映由该cLass对象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超级接口继承的类
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("----------------------------------------------------");

        //Method[] getDeclaredMethods()返回一个包含方法对象的数组,方法对象反映由class对象表示的类或接口的所有声明方法
        //包括public,protected,default (package) 访问和私有方法,但不包括继承方法。
        Method[] declaredMethods = c.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("----------------------------------------------------");

        //Method getMethod (String mame,CLass<?>... parameterTypes)
        //返回一个方法对象,该对象反映由该class对象表示的类或接口的指定公共成员方法
        //public void method1()
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        Method method1 = c.getMethod("method1");

        //Object invoke (Object obj,Object... args)在具有指定参数的指定对象上调用此方法对象表示的基础方法
        method1.invoke(obj);


        //Method getDeclaredMethod (String mame,CLass<?>... parameterTypes)
        // 返回一个方法对象,它反映此表示的类或接口的指定声明的方法 class对象。
    }
}

/**
public java.lang.String reflection.demo2.Student.toString()
public void reflection.demo2.Student.method2(java.lang.String)
public java.lang.String reflection.demo2.Student.method3(java.lang.String,int)
public void reflection.demo2.Student.method1()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
----------------------------------------------------
public java.lang.String reflection.demo2.Student.toString()
private void reflection.demo2.Student.function()
public void reflection.demo2.Student.method2(java.lang.String)
public java.lang.String reflection.demo2.Student.method3(java.lang.String,int)
public void reflection.demo2.Student.method1()
----------------------------------------------------
method
**/

test1

练习:通过反射实现如下操作
Student s = new StudentO;
s.method1();
s.method2("Bob");
String ss = s.method3("Bob" ,18);
System.out.println(ss);
s.function();
package reflection.demo5;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c = Class.forName("reflection.demo2.Student");
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        //public void method1()
        Method method1 = c.getMethod("method1");
        method1.invoke(obj);

        //public void method2(String s)
        Method method2 = c.getMethod("method2", String.class);
        method2.invoke(obj, "Bob");

        //public String method3(String s, int i)
        Method method3 = c.getMethod("method3", String.class, int.class);
        Object o = method3.invoke(obj, "Bob", 18);
        System.out.println(o);

        //private void function()
        Method function = c.getDeclaredMethod("function");
        function.setAccessible(true);
        function.invoke(obj);
    }
}

/**
method
method:Bob
Bob/18
function
**/

practice1

练习1:我有一个ArrayList<Integer>集合,现在我想在这个集合中添加一个字符串数据,如何实现?
package reflection.demo6;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        ArrayList<Integer> arr = new ArrayList<Integer>();
        arr.add(100);
        arr.add(200);

        Class c = arr.getClass();
        Method addMethod = c.getMethod("add", Object.class);

        addMethod.invoke(arr, "hello");
        addMethod.invoke(arr, "world");
        System.out.println(arr);
    }
}
/**
[100, 200, hello, world]
**/

practice2

通过配置文件运行类中的方法

Student

package reflection.demo6;

public class Student {
    public void study(){
        System.out.println("good good study, day day up!");
    }
}

Teacher

package reflection.demo6;

public class Teacher {
    public void teach(){
        System.out.println("teach students");
    }
}

Class.txt

className=reflection.demo6.Student
methodName=study

main

package reflection.demo6;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Test2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Properties prop = new Properties();
        FileReader fr =new FileReader("Class.txt");
        prop.load(fr);
        fr.close();
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

        Class c = Class.forName(className);
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        Method method = c.getMethod(methodName);
        method.invoke(obj);
    }
}
/**
good good study, day day up!
**/
posted @ 2021-08-12 13:22  Th0r  阅读(48)  评论(0编辑  收藏  举报