黑马程序员---Java中使用反射

                                                   关于Java中的反射
                 --------- android培训java培训、java学习型技术博客、期待与您交流! ------------

1. 反射概念
  反射就是将一个类的class文件,封装成一个对象
  从class中获取(解剖)类中的成员,并且运行起来

 反射有关系的类
  java.langClass 封装class文件的
  java.lang.reflect.Constructor 封装构造方法的
  java.lang.reflect.Field 封装成员变量的
  java.lang.reflect.Method 封装成员方法的


//以下所有代码的演示都会使用此类

/*
 *
 * 用于反射演示的Person类
 *
 */
public class Person {
 private String name;
 private int age;
 public String email;
 
 public Person(){System.out.println("空参赛构造");}
 public Person(String name,int age){
  this.age = age;
  this.name = name;
  System.out.println("两个参数构造");
 }
 
 public Person(String name)
 {
  this.name = name;
  System.out.println("私有构造");
 }
 
 //定义多个普通方法
 public void speak()
 {
  System.out.println("say");
 }
 public void show(int x)
 {
  System.out.println("一个人的x"+x);
 }
 public String toString()
 {
  return "Person " +name+"......"+age+"..."+email;
 }
// {
// System.out.println("构造代码要建对象,才运行");
// }
//
// static{
// System.out.println("静态代码块,加载类的时候运行");
// }
}

//==================================================
2.获取反射的三种方式

  编译后的class文件,对象的方式
  描述类是Class,三种方式的返回值类型也是Class类型
A. 对象.getClass()
B. 类名.class
C. Class.forName()获取
  推荐使用:Class.forName方式获取一个类的字节码文件对象 灵活方便,你的类名可以通过字符串参数传递的


public class ReflectDemo {
 public static void main(String[] args) throws ClassNotFoundException {
 //第一种,通过对象获取 Object类的方法 class<?> getClass()
  Person p = new Person();
  Class c1 = p.getClass();
  System.out.println(c1);
 
 
  //第二种,通过类,直接获取,多线程中,任何一个数据类型,都有一个静态成员变量class
  //静态成员变量,返回这个累的class的文件对象
  Class c2 = Person.class;
  System.out.println(c2);
 
  System.out.println(c1==c2);//t
  System.out.println(c1.equals(c2));//t
  //以上结果都是T,因为你的Person.class 对象只有一份
//第三种,通过forName(String className)
  Class c3 = Class.forName("cn.itcast.reflects.Person");
  System.out.println(c3);
// method("cn.itcast.reflects.Person") //推荐这种方式
 }
 private static void method(String className) throws ClassNotFoundException
 {
  Class c = Class.forName(className);
  System.out.println(c);
 }
}


//==================================================

3. 通过class文件对象,获取构造方法并运行构造方法
  Class类的方法Constructor<?>[] getConstructors() 公共权限的
  获取构造方法,返回数组
  Constructor返回值类型,是描述构造方法的类
  Class类的方法获取一个构造方法
  Constructor getConstructor(Class...c)传递参数,传递和构造方法一致的参数,就可以获取到构造方法了
  获取到了构造方法,如何运行呢
  Constructor类方法 Object newInstance(Object... initargs) 创建类的对象,构造方法就运行了
 
//反射获取构造方法并运行
import java.lang.reflect.*;
public class ReflectDemo1 {
 public static void main(String[] args) throws Exception {
  //获取Person字节码文件对象
  Class clazz = Class.forName("cn.itcast.reflects.Person");
  //通过字节码文件对象获取构造方法getConstructors方法,返回构造方法数组
  Constructor[] cons = clazz.getConstructors();
  for(Constructor c : cons){
   System.out.println(c);
  }
  //获取一个构造方法,并运行
  Constructor con = clazz.getConstructor();
  System.out.println(con);
  Object obj = con.newInstance();
  System.out.println(obj);
 
 
  //获取一个有参数的构造方法,并运行‘
  Constructor con2 = clazz.getConstructor(String.class,int.class); //
  System.out.println(con2);
  obj = con2.newInstance("张三",23);
  System.out.println(obj);
 
 }
}
//===================


  获取私有构造方法,并运行,单例模式无效了
  Class类的getDeclaredConstructor()获取私有的构造方法
  void setAccessible(boolean flag) 方法是Constructor父类AccessibleObject类的方法
  运行时期,取消Java检查(权限) ,暴力访问 


//获取私有构造方法运行 
import java.lang.reflect.*;
public class ReflectDemo3 {
 public static void main(String[] args) throws Exception {
  Class clazz = Class.forName("cn.itcast.reflects.Person");
  //获取私有构造
/* Constructor[] cons = clazz.getDeclaredConstructors();
  for(Constructor c : cons){
   System.out.println(c);
  }*/
  Constructor con = clazz.getDeclaredConstructor(String.class);
  con.setAccessible(true);
  Object obj = con.newInstance("haha");
  System.out.println(obj);
 
 }
}


//=====
/*
 * 反射打破单例模式
 */ 
import java.lang.reflect.Constructor;
class Single{
 private Single (){}
 private static final Single s = new Single();
 public static Single getInstance(){
  return s;
 }
}
public class ReflectDemo4 {
 public static void main(String[] args) throws Exception{
  Class clazz = Class.forName("cn.itcast.reflects.Single");
  Constructor con = clazz.getDeclaredConstructor();
  con.setAccessible(true);
  Object obj = con.newInstance();
  System.out.println(obj);
  obj = con.newInstance();
  System.out.println(obj);
 }
}
//==================================================
4. 通过class文件对象,获取成员变量,并修改值
  Class类的方法Field[] getFields()类中的成员变量,公共的
  Class类的方法 Field getField(String name) 获取指定的成员变量,公共的
  传递一个变量名
  Field类的方法set(obj,修改后的新值)修改值

/*
 * 获取成员变量,并运行
 */
import java.lang.reflect.*;
public class ReflectDemo5 {
 public static void main(String[] args)throws Exception {
  Class clazz = Class.forName("cn.itcast.reflects.Person");
  //利用Class类的方法getFields()获取成员变量
  /*Field[] fields = clazz.getFields();
  for(Field f : fields){
   System.out.println(f);
  }*/
 
  Object obj = clazz.newInstance();
  //获取一个成员变量email
  Field field = clazz.getField("email");
  field.set(obj, "[email protected]");
  System.out.println(obj);
 
  //获取私有成员变量age修改值
  Object obj2 = clazz.newInstance();
  Field field2 = clazz.getDeclaredField("age");
  field2.setAccessible(true); //暴力访问
  field2.set(obj2, 333);
  System.out.println(obj2);
 }
}

//==================================================
5. 通过class文件对象,获取成员方法,并运行
 Class类的方法 Method[] getMethods()获取类中,所有的公共的成员方法,包括继承的
 Class类的方法,Method getMethod(字符串的方法名,要获取的方法的参数列表)获取一个方法
 Method类中有一个方法,可以运行获取到的方法,名字invoke(对象,运行方法时传递的实际参数列表...)
 运行方法的方法
 Class类的方法Method[] getDeclaredMethods() 公共的,私有的,受保护,但是不包括继承的

//反射获取成员方法,并运行
import java.lang.reflect.*;
public class ReflectDemo6 {
 public static void main(String[] args) throws Exception{
 
  Class clazz = Class.forName("cn.itcast.reflects.Person");
  //通过Class类的方法getMethods()
/* Method[] method = clazz.getMethods();
  for(Method m : method)
  {
   System.out.println(m);
  }*/
  Object obj = clazz.newInstance();
  //获取一个成员方法
  Method method1 = clazz.getMethod("speak");
  //
  //使用Method类的invoke方法,运行获取到的方法
  method1.invoke(obj);
 
  //获取一个参数的 int show方法运行
  Method method2 = clazz.getMethod("show", int.class);
  method2.invoke(obj, 123);
 }
 
 
}
//================
/*
 * 获取私有的成员方法运行
 */
import java.lang.reflect.*;
public class ReflectDemo7 {
 public static void main(String[] args)throws Exception {
  Class clazz = Class.forName("cn.itcast.reflects.Person");
  Method[] methods = clazz.getDeclaredMethods();
  for(Method m : methods){
   System.out.println(m);
  }
  Object obj = clazz.newInstance();
  //获取私有的run方法
  Method method = clazz.getDeclaredMethod("run");
  method.setAccessible(true);
  method.invoke(obj);
 }
}



//=====================================
反射绕过编译器检查,将不同的数据类型,存储到带有泛型的集合(泛型的擦除)

import java.lang.reflect.*;
import java.util.*;
public class GenericReflect {
 public static void main(String[] args)throws Exception {
  ArrayList<String> array = new ArrayList<String>();
  array.add("123");
 
  //Class clazz =Class.forName("cn.itcast.reflects.GenericReflect");
  Class clazz = array.getClass();
  //Class clazz = GenericReflect.class;
  Method method = clazz.getMethod("add", Object.class);//改成了Object类型的
  method.invoke(array, 123);
  method.invoke(array,false);
  System.out.println(array);
 
  Iterator it = array.iterator();
  while(it.hasNext())
  {
   System.out.println(it.next());
  }
 }
}

                          --------- android培训java培训、java学习型技术博客、期待与您交流! ------------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章