码迷,mamicode.com
首页 > 编程语言 > 详细

java--反射

时间:2017-11-10 23:02:32      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:垃圾回收   原因   public   dep   理解   ati   泛型使用   protect   nat   

反射的基本概念

  如果正常的情况下,如果使用一个类,则必须按照如下的步骤操作:

    • 使用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,此泛型使用不到

    代码演示: 在这里是不能接受的了这个返回值的,
         技术分享

    这里就是解决上面错误的代码实现: 从中我们就可以看到我们不一定非要使用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

 

     所以如果现在想要进行制定构造方法的调用,就必须将关注点放在Contructor类中。

    public T newInstance?(Object... initargs)
              throws InstantiationException,
                     IllegalAccessException,
                     IllegalArgumentException,
                     InvocationTargetException  使用由此Constructor对象表示的构造函数,使用指定的初始化参数创建和初始化构造函数的声明类的新实例
 代码实现:实例化刚才的Student对象
  
import java.lang.reflect.Constructor;
class Student{
    public  Student(String str) {
        System.out.println("构造方法Student:    "+str);
    }
}
public class GetStringConstructor { public static void main(String[] args) throws Exception { Class<?> forName = Class.forName("test.Student"); Constructor<?> constructors = forName.getConstructor(String.class);//从这可以看到要与想调用的构造方法的参数类型一直才可以 constructors.newInstance("纯菜鸟-java-反射"); } }
执行结果:构造方法Student:    纯菜鸟-java-反射 time:40.00

 


  

 

    

 

 

分析简单java类与反射的联系

利用反射解决servlet代码过多的问题

用反射来解决工厂模式,代理设计模式的操作

动态代理设计模式,CGLIB实现的动态代理设计模式

使用Annotion编写注解操作

java--反射

标签:垃圾回收   原因   public   dep   理解   ati   泛型使用   protect   nat   

原文地址:http://www.cnblogs.com/wzqjy/p/7816673.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!