反射的基本概念
  如果正常的情况下,如果使用一个类,则必须按照如下的步骤操作:
    • 使用import 导入类所在的包;(类:java.lang.Class)
    • 明确的使用类名称或借口名称定义对象;
    • 通过关键字new进行类对象实例化;(构造方法:java.lang.reflect.Constructor);
    • 产生对象可以使用“对象.属性”进行类中属性的调用(属性:java.lang.reflect.Field);
    • 通过“对象.方法()”调用类中方法(方法:java.lang.reflect.Method);
  反射过程不需要有明确类型的对象,所有的对象使用Object表示
    1. 可以直接使用Object与反射机制的混合调用类中的方法。
Object类中的所有方法以及每一个方法使用上的注意事项
  • 对象克隆:protected Object clone​() throws CloneNotSupportedException 创建并返回此对象的副本。 “复制”的精确含义可能取决于对象的类。
    •   为什么克隆方法返回的是Object? 答:因为克隆方法可能针对所有类对象使用,为了统一参数用Object
    •   克隆对象所在的类一定要实现java.lang.Cloneable接口而子类只需要继续调用Object 的克隆方法就可以成功实现克隆操作;
  • 对象输出:public String toString​() 返回对象的字符串表示形式。
    •   直接输出对象时会默认调用toString()方法
      •   原因:由于平时我们会直接System.out.println();来直接输出对象,那么我们打开源码看一下为什么会默认调用toString()方法
                在printStream类中找到print输出方法 如下 
            public void print(Object obj) {write(String.valueOf(obj));}
                 可以看到他在输出的时候调用了String的valueOf方法,下面打开valueOf方法源码
             public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
            从中我们可以看到如果传入的对象不为null的话就会自动的调用toString()方法然后返回
  • 对象比较:public boolean equals​(Object obj) 指示一些其他对象是否等于此。
    •   有哪些时候会隐式调用此方法??
      • 当我们保存Set集合时,会依靠hashCode()和equals()判断对象是否重复;
  • 取得对象的hash码:public boolean equals​(Object obj) 指示一些其他对象是否等于此。
    •   可以理解为每一个对象的唯一编码,比较时会先判断编码是否相同,然后再调用equals方法判断是否相同
  • 取得Class类对象:public final Class<?> getClass​() 返回此Object的运行时类。
    •   通过一个已经实例化好的对象进行对象的反射操作;
  • 线程等待:public final void wait​() throws InterruptedException 导致当前线程等到另一个线程调用该对象的notify()方法或notifyAll()方法。 换句话说,这个方法的行为就好像简单地执行调用wait(0)
    •   执行到此代码时线程要等待执行,直到执行notify()或者notifyAll()方法来唤醒线程;
  • 一个线程唤醒:public final void notify​() 唤醒正在等待对象监视器的单个线程。
  • 全部线程唤醒:public final void notifyAll​() 唤醒正在等待对象监视器的所有线程。
  • 垃圾回收前释放:protected void finalize​() throws Throwable 已过时。 定稿机制本质上是有问题的。 定稿可能导致性能问题,死锁和挂起。
    •   当使用gc回收无用的垃圾空间时默认调用;
        
 
Class类
    class类是整个反射的操作源头,而类的定义如下:
    public final class Class<T> extends Object implements
          Serializable, GenericDeclaration, Type, AnnotatedElement
 
    如果想要使用Class类进行操作,那么必须首先产生Class类的实例化对象,而有三种方法可以去的Claas类的实例化对象
    • Object类提供了一个返回Class类对象的方法:public final Class<?> getClass​();
    • 利用“类.class”取得,日后建的最多的就是在Hibernate上;
    • 利用Class类的static方法取得,public static Class<?> forName​(String className) throws ClassNotFoundException  返回与给定字符串名称的类或接口相关联的Class对象。
      如果是程序设计人员,使用最多的方法一定是forName()方法,但是如果是使用者会使用“类.class”。工厂设计模式最好利用反射机制来解决耦合问题。
利用反射实例化对象
    Class类如果使用了forName()方法之后,就可以使用Class类定义的newInstance()方法默认去调用类之中的无参构造器进行操作
        public T newInstance​() throws InstantiationException, IllegalAccessException,此泛型使用不到
    代码演示: 在这里是不能接受的了这个返回值的,
         
java--反射的基本概念

 

    这里就是解决上面错误的代码实现: 从中我们就可以看到我们不一定非要使用new实例化对象,只要我们有一个类的完整名称也可以实例化对象
public class R {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("test.Student");
//jdk 1.9 开始直接使用的newInstance()方法已经过时,可以使用下面的方式来调用newInstance()方法 
//相当于关键字new实例化对象。等价于 Object newInstance = new Student();Object newInstance = cls.getDeclaredConstructor().newInstance(); } } 
class Student{ public Student() { System.out.println("构造方法Student"); 
} }
    执行结果:构造方法Student
 
    但是如果使用反射实例化对象,必须要求类中存在有无参构造方法,因为newInstance()方法只能找到无参。如果没有无参构造函数如下:
      Exception in thread "main" java.lang.NoSuchMethodException:  
     如果想找到无参构造怎么办?操作构造方法
操作构造方法:
   为了解决NoSuchMethodException错误,这个时候这能取得类之中的构造方法,传递所需要的参数后才能使用。
   在Class类里面定义了可以取得一个类中的构造方法的操作:
    •   public Constructor<T> getConstructor​(Class<?>... parameterTypes)                                    (重点使用)
throws NoSuchMethodException, SecurityException
       返回一个Constructor对象,及时取得类中制定参数的构造,该对象反映由此Class对象表示的类的指定公共构造函数。
    • public Class<?>[] getDeclaredClasses​() throws SecurityException
            返回一个Class对象的数组,就是全部构造,反映了所有被声明为由这个Class对象表示的类的成员的类和接口。
      代码演示:取得String中的全部构造方法。
    
import java.lang.reflect.Constructor;
 public class GetStringConstructor {
 public static void main(String[] args) throws Exception {
 Class<?> forName = Class.forName("java.lang.String");
 Constructor<?>[] constructors = forName.getConstructors();//得到所有构造
 for (int i = 0; i < constructors.length; i++) { System.out.println(constructors[i]); } } }

 执行结果:

public java.lang.String(byte[])
public java.lang.String(byte[],int,int)
public java.lang.String(byte[],java.nio.charset.Charset)
public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int,int,java.nio.charset.Charset)
public java.lang.String(java.lang.StringBuilder)
public java.lang.String(java.lang.StringBuffer)
public java.lang.String(char[],int,int)
public java.lang.String(char[])
public java.lang.String(java.lang.String)
public java.lang.String()
public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException
public java.lang.String(byte[],int)
public java.lang.String(byte[],int,int,int)
public java.lang.String(int[],int,int
View Code

相关文章:

  • 2022-02-05
  • 2022-12-23
  • 2021-05-10
  • 2021-10-14
  • 2022-02-03
  • 2022-12-23
  • 2021-10-11
猜你喜欢
  • 2021-04-17
  • 2021-10-14
  • 2021-09-11
  • 2021-05-30
  • 2022-12-23
  • 2021-12-06
相关资源
相似解决方案