Java_反射_基础

反射

1.什么是反射 ?

2.如何获取反射类Class

3.如何获取属性类Field

4.如何获取方法类Method

5.如何获取构造类Constructor

6.如何获取注解类Annotation

7.写个例子 : 模拟SpringIOC功能

1. 什么是反射?--框架设计的灵魂

(1) 框架 : 就是一种半成品 好处:可以提高开发效率,使代码更加简洁

(2) 反射: 把类中成员抽取为其他类的过程叫做反射

2. 如何获取反射类Class

(1) Class.forName("全路径"); 通 过类的全类名字符串来获取

例子 : Spring框架<bean id="" class="类的全路径"/> --可以获取类对象--Class-->类对象

(2) 类名.class; 通过类名来获取

例子 :mybatis框架 session.getMapper(StudentDao.class)

(3) 对象名.getClass(); 通过对象类获取

当知道该类对象时,可以通过对象来获取反射类

  package com.qy143.demo01;

public class demo01 {
   public static void main(String[] args) throws ClassNotFoundException {
       // 获取Class类的方式
       // 1. 通过类的全类名字符串来获取
       Class aClass = Class.forName("com.qy143.demo01.Student");

       // 2. 通过类名来获取
       Class bclass = Student.class;

       // 3. 对象
       Student s=new Student();
       Class cClass= s.getClass();

       // 思考: 上面这些方式获取到的Class对象的地址是否一样?
       System.out.println(aClass==bclass); // == 比较引用地址
       System.out.println(aClass==bclass); // 三者皆为true
       System.out.println(cClass==bclass);  // 任何一个类的反射类对象只有一个
  }
}
class Student{
   private String name;
   private int age;
   public void  show(){
       System.out.println("++++++++++++++++++++show+++++++++++++++++++++");
  }

   public Student() {
  }
}

3. 如何通过反射类获取对应的类对象

例子:

  
package com.qy143.demo2;
public class Test02 {
   public static void main(String[] args) throws IllegalAccessException, InstantiationException {
       Class<Student> aClass = Student.class;// 得到Student的反射类对象
       Student student = aClass.newInstance(); // 通过反射类得到对应的类对象
       System.out.println(student);
  }
}

class Student{
   private String name;
   private int age;
   public void  show(){
       System.out.println("++++++++++++++++++++show+++++++++++++++++++++");
  }

   public Student() {
  }

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

4. 获取Field类的方式

  
Field getDeclaredField(String name) : 获取当前类中指定名称的属性对象 (不包括父类)

Field getDeclaredFields() :获取当前类中所有的属性对象(不包括父类)

Field getField(String name) :获取指定public修饰的属性名的Field对象[包含父类的属性]

Field getFields() : 获取所有public修饰的属性对象[包含父类的属性]

例子:

  
package com.qy143.demo03;


import java.lang.reflect.Field;
import java.util.concurrent.Callable;

public class Test03 {
   public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
       System.out.println("++++++++++++++++++获取public修饰的对象++++++++++++++++++=");
       Class<?> aClass =Class.forName("com.qy143.demo03.Student");
       Field nameField = aClass.getField("name");// 获取指定的name属性对象
       System.out.println(nameField);
       Field sexfield = aClass.getField("sex");
       System.out.println(sexfield);


       System.out.println("+++++++++++++++++++获取本类中指定的属性对象+++++++++++++++++++++++++++++");
       Field namefield2 = aClass.getDeclaredField("name");// 获取本类中的属性对象
       System.out.println(namefield2);
       Field ageield2 = aClass.getDeclaredField("age");// 获取本类中的属性对象
       System.out.println(ageield2);
//       Field sexfield2 = aClass.getDeclaredField("sex");// 获取本类中的属性对象
//       System.out.println(sexfield2);

       System.out.println("+++++++++++++++++++获取全部public修饰的属性对象++++++++++++++++++++++++");
       Field[] fields =aClass.getFields();
       for (Field f:fields){
           System.out.println(f);
      }

       System.out.println("++++++++++++++++++++++++++获取本类中所有属性对象");
       Field[] declaredFields =aClass.getDeclaredFields();
       for (Field f:declaredFields){
           System.out.println(f);
      }
  }
}

class Father{
   public String sex;
}
class Student extends Father{
   public String name;
   private int age;
   public void  show(){
       System.out.println("++++++++++++++++++++show+++++++++++++++++++++");
  }

   public Student() {
  }

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

Field类中操作有哪些

  
get(Object obj); 返回该所表示的字段的值 Field ,指定的对象上
set(Object obj,Object value); :为执行属性赋值
serAccessible(boolean) : 设置属性的可见性

例子:

  
package com.qy143.demo04;
import java.lang.reflect.Field;

public class Test04 {
   public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
       Class<?> aClass = Class.forName("com.qy143.demo04.Student");
       Object o =aClass.newInstance();
       Field namefield = aClass.getField("name");
       System.out.println(namefield.get(o)); // 获取name属性值
       namefield.set(o,"张三"); // 为name属性对象赋值
       System.out.println(namefield.get(o));


       Field agefield = aClass.getDeclaredField("age");
       agefield.setAccessible(true); // 设置私有属性的可见性 , 不建议使用因为其打破了面向对象的封装性
       agefield.set(o,15); // 报错了   因为私有的无法访问
       System.out.println(o);
  }

}

class Father{
   public String sex;
}
class Student extends Father {
   public String name;
   private int age;
   public void  show(){
       System.out.println("++++++++++++++++++++show+++++++++++++++++++++");
  }

   public Student() {
  }

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

 

5.如何获取方法类Method

  
Method getDeclaredMethod(String name, Class<?>... parameterTypes) : 获取当前类中指定的方法名 (不包括父类)

Method getDeclaredMethods() : 获取当前类中所有的方法 (不包括父类)

Method getMethod(String name, Class<?>... parameterTypes) : 获取指定类中的public修饰的方法 (包含父类)

Method getMethods() : 获取指定类全部public方法(包含父类)

例子:

  
package com.qy143.demo05;


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

public class Test05 {
   public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
       Class<Student> studentClass = Student.class;
       Student student = studentClass.newInstance();
       Method show = studentClass.getMethod("show");
       System.out.println(show);

       System.out.println(show.getModifiers());// 获取修饰符 1 public 2 private..等等
       Method print = studentClass.getMethod("print",int.class,String.class); // 可以调用父亲的方法并且加参数
       System.out.println(print);

       Method fun = studentClass.getDeclaredMethod("fun");
       System.out.println(fun);

       // 回调该方法
       show.invoke(student);//Object o 对象名,Object... args 参数

       fun.setAccessible(true);// 调用私有方法时需要设置可见性
       fun.invoke(student);//Object o 对象名,Object... args 参数

       Object o=print.invoke(student,15,"翻斗大街");
       System.out.println(o);// 无返回值 为null

       // 如果方法有返回值呢??
       Method toString = studentClass.getMethod("toString");
       Object invoke=toString.invoke(student);
       System.out.println(invoke);

  }
}

class Father{
   public String sex;
   public void print(int age,String addresss){
       System.out.println("父类中的print方法"+age+" "+addresss);
  }

}
class Student extends Father {
   public String name;
   private int age;
   public void  show(){
       System.out.println("++++++++++++++++++++show方法+++++++++++++++++++++");
  }

   public Student() {
  }

   private void fun(){
       System.out.println("++++++++++++++++++++fun方法+++++++++++++++++++++");
  }

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

6.如何获取构造类Constructor

  
getConstructor(Class...):获取某个public的Constructor;

getDeclaredConstructor(Class...):获取某个Constructor;

getConstructors():获取所有public的Constructor;

getDeclaredConstructors():获取所有Constructor。

调用非public的Constructor时,必须首先通过setAccessible(true)设置允许访问。
使用Constructors中具有的的方法,如果类中没有无参构造函数时要newInstacne

例子:

  
package com.qy143.demo06;


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

public class Test06 {
   public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
       Class<Teacher> teacherClass = Teacher.class; // 只能调用无参构造函数
//       Constructor<Teacher> constructor = teacherClass.getConstructor(); // 无参构造对象
//       Teacher teacher = constructor.newInstance();
//       System.out.println(teacher);

       Constructor<Teacher> constructor = teacherClass.getConstructor(String.class);// 获取参数类型为String类型的一参构造函数
       Teacher teacher = constructor.newInstance("张三");
       System.out.println(teacher);

       Constructor<Teacher> constructor1 = teacherClass.getConstructor(String.class,int.class);// 获取参数类型为String类型的多参构造函数
       Teacher teacher1 = constructor1.newInstance("李四",15);
       System.out.println(teacher1);

  }
}


class Teacher {
   public String name;
   private int age;
   public void  show(){
       System.out.println("++++++++++++++++++++show方法+++++++++++++++++++++");
  }

   public Teacher() {
       System.out.println("无参");
  }

   public Teacher(String name) {
       System.out.println("单参");
       this.name = name;
  }

   public Teacher(String name, int age) {
       System.out.println("多参");
       this.name = name;
       this.age = age;
  }

   private void fun(){
       System.out.println("++++++++++++++++++++fun方法+++++++++++++++++++++");
  }

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

 

7.如何获取注解类Annotation

  
A getAnnotation(类<A> annotationClass) 返回指定注解
getAnnotations() 返回全部注解

可以获取到类上的注对象,还可以获取属性上的注解对象

例子:

  
package com.qy143.demo07;


import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.jws.WebService;
import javax.xml.ws.ServiceMode;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test07 {
   public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
       System.out.println("获取注解上的注解对象");
       Class<Doctor> doctorClass = Doctor.class;
       Service annotation = doctorClass.getAnnotation(Service.class);
       System.out.println(annotation);
       System.out.println(annotation.value());

       System.out.println("获取属性上的注解对象");
       Field name = doctorClass.getDeclaredField("name");
       JsonProperty annotation1 = name.getAnnotation(JsonProperty.class);
       System.out.println(annotation1);
       System.out.println(annotation1.required());

       System.out.println("获取方法上的注解");
       Method hello = doctorClass.getMethod("hello");
       RequestMapping annotation2 = hello.getAnnotation(RequestMapping.class);
       System.out.println(annotation2.value());


  }
}
@Service(value = "hello")
class Doctor{
   @JsonProperty(value = "n",required = true)// value required都是注解的属性
   private String name;

   @RequestMapping(value = {"hello2","hahaha","hehe"})
   public void hello(){
       System.out.println("hello");
  }
}

 

8.写个例子 : 模拟SpringIOC功能

写一个框架:

1.写个属性文件

  
classname=com.qy143.Food
method=show

2.随便写两个方法

  
public class Food {
   public void show(){
       System.out.println("Food中的show方法");
  }
}
  
public class Student {
   public void fun(){
       System.out.println("Student类中的fun方法");
  }
}

3.测试呗

  
package com.qy143;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class Test {
   public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
       // 1. 读取属性文件
       InputStream resourceAsStream = Test.class.getClassLoader().getResourceAsStream("a.properties");
       Properties properties = new Properties();
       properties.load(resourceAsStream);

       // 2. 读取属性文件中的类名
       String classname = properties.getProperty("classname");

       // 3.根据类的名称回去反射类对象
       Class<?> aClass = Class.forName(classname);

       // 4.根据反射类 创建对应对象
       Object o = aClass.newInstance();

       // 5. 获取属性文件中执行的方法名
       String methodname = properties.getProperty("method");


       // 6. 获取方法对象
       Method method = aClass.getMethod(methodname);

       // 7. 执行该方法
       method.invoke(o);
  }
}

改变properties中的属性就,就ok,算是垃圾框架完成

总结 :

  
1. 获取反射类: Class
2. 获取属性类: Field
3. 获取方法类: Method
4. 获取构造类: Constructor
5. 获取注解类: Annotation

 

posted @ 2021-12-20 18:57  Oner_z  阅读(21)  评论(0)    收藏  举报