二十、反射机制、可变长参数

1、SUN提供的反射机制中的类:

1)反射机制的含义:
java反射机制是在运行状态中,对于任何一个类,都能够知道这个类的属性和方法;对于任何一个对象,都能调用它的任何一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制

2)动态语言的含义:
程序运行时,运行改变程序结构或变量类型,这种语言称为动态语言。从该观点上看,perl、python、ruby是动态语言。C++、java、C#不是动态语言。但是java语言有一个非常突出的动态机制:Reflection。这个动态机制在java上指的是:我们可以于运行时加载、探知、使用编译期间完全未知的Classes,换句话说java程序可以加载一个运行时才得知名称的Class,获悉其完整结构(但不包含methods定义),并生成其对象实体,或对其fields设置,或唤起methods。

3)java反射机制主要提供的功能
 在运行时判断任意一个对象所属的类;
 在运行时构造任意一个类的对象;
 在运行时判断任意一个类所具有的成员方法和成员变量;
 在运行时调用任意一个对象的方法,生成动态代理;

java.lang.Class; //Class类 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的
java.lang.reflect.Constructor;
java.lang.reflect.Filed;
java.lang.reflect.Method;
java.lang.reflect.Modifier;

//获取Class类型对象的三种方式:
public class ReflectTest01 {
 public static void main(String[] args) throws ClassNotFoundException {
    //方法一:c1引用保存内存地址指向堆中的对象,给对象代表的是Employee.class整个类
    Class c1 = Class.forName("反射机制.Employee");//此处要是不加包名的话可能会报类没有找到的异常

    //方法二:java中每一个类型都有class属性,其形象的表示了c2代表整个Employee.class文件
    Class c2=Employee.class;
  
    //方法三:java语言中任何一个java对象都有getClass方法
    Employee e1=new Employee();
    Class c3=e1.getClass();
    System.out.println(c1==c2);
    System.out.println(c2==c3);
 }
}

public class Employee {
   String name;
   public Employee(){
  
   }
   public Employee(String name){
      this.name=name;
   }
   public void m1(String name){
      System.out.println(name+"在工作");
   }
}

|Class类中静态语句块的执行|

public class ReflectTest02 {
   public static void main(String[] args) throws ClassNotFoundException {
    //不会执行静态语句块
    Class class1=A.class;
  
    //将A.class文件装载到jvm中的过程,静态语句块会执行
    Class class2=Class.forName("反射机制.A");
  
    //静态语句块会执行
    A a=new A();
    Class class3=a.getClass();
    try {
       A a2=(A) class3.newInstance();     //创建此 Class 对象所表示的类的一个新实例
       System.out.println(a==a2);//false
   
    } catch (InstantiationException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    } catch (IllegalAccessException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    }
}
class A{
   static {
      System.out.println("A-->中的静态语句块执行");
   }
}

2、可变长参数

public class KeBianChengCanShu {
 public static void main(String[] args) {
    m1();
    m1(3);
    String[] s={"体育","音乐","旅游","美食"};
    m2(s);
 }
   //m1方法具有一个int 类型的可变长参数:
   public static void m1(int... a){//m1方法在调用的时候传递的实参可以是0-N个
     System.out.println("具有可变长参数的m1方法执行");
 }
   //如果有更精确匹配参数的该方法,则调用该方法,不会再去执行可变长参数的那个方法
   public static void m1(int i){
    System.out.println("具有精确匹配参数的m1方法执行");
 }
 
 //可变长参数可等同看做一个数组:
 public static void m2(String[] args){
    for(int i=0;i<args.length;i++){
    System.out.println(args[i]);
  }
 }
 //可变长参数只能出现一次,并且只能出现在所有参数的最后一位
 //public static void m3(String... a,int i){}  //这种写法是不对的
   public static void m3(int i,String... s){
  
   }
}

|Properties属性集类的用法|:读取属性配置文件中的key 和 value值

dbProperties文件中的内容:

username:zhangsan
password:zs123

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class ReflectTest03 {
   public static void main(String[] args) {
    //创建属性对象:
    Properties p=new Properties();
    FileInputStream fiStream=null;
    try {
    //创建输入流
     fiStream=new FileInputStream("src/反射机制和可变长参数/dbProperties");
   
    } catch (FileNotFoundException e) {
     // TODO Auto-generated catch block
       e.printStackTrace();
    }
    try {
      // 从输入流中读取属性列表(键和元素对) 
       p.load(fiStream);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    try {
       fiStream.close();
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
    //通过key获取value:
    String s1=p.getProperty("username");
    String s2=p.getProperty("password");
    System.out.println(s1);
    System.out.println(s2);
 }
}

|示例:反射机制给属性赋值|

 

import java.lang.reflect.Field;

 

public class ReflectTest06 {
 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException,         IllegalAccessException {
    //以前给类属性赋值
    User user=new User();
    user.name="zhangsan";
    System.out.println(user.getName());
  
    //获取类
    Class c=Class.forName("反射机制和可变长参数.User");
   //获取name属性-->可以通过打破封装性,对其赋值
    Field nameField=c.getDeclaredField("name");
  
    //打破封装
    nameField.setAccessible(true);
    Object ob=c.newInstance();
    //给ob 对象的name属性赋值 nana
    nameField.set(ob, "nana");
    System.out.println(nameField.get(ob));
   }
}

 

|示例:用反射机制反编译某个类中的属性信息|

 

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

 

public class ReflectTest05 {
 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException {
    Class c=Class.forName("反射机制和可变长参数.User");
    //获取类名:
    System.out.println(c.getSimpleName());
    //获取所有的Public修饰的属性
    Field[] fields=c.getFields();
    System.out.println(fields.length);
    for(int i=0;i<fields.length;i++){
    //属性对象代表的属性的简单的名字
     System.out.println(fields[i].getName());
    //属性的详细的信息,包括该属性的修饰符 
     System.out.println(fields[i]);
  }
    Field fields2=c.getDeclaredField("name");
    System.out.println(fields2);
  
    StringBuffer sb=new StringBuffer();
    sb.append(Modifier.toString(c.getModifiers())+"class"+c.getSimpleName()+"{\n");
      for(Field fs:fields){
        sb.append("\t");
        sb.append(Modifier.toString(fs.getModifiers())+" ");
        sb.append(fs.getType().getSimpleName()+" ");
        sb.append(fs.getName()+";\n");
     }
    sb.append("}"); 
    System.out.println(sb);  
 }
}

 

|示例:通过反射机制执行某个特定的方法|

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
  /*
   通过反射机制执行某个方法
  */
public class ReflectTest08 {
 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Class c=Class.forName("反射机制和可变长参数.CustomerService");
    //获取某个特定的方法:通过方法名+形参列表
    Method m=c.getDeclaredMethod("login",String.class,String.class);
    //通过反射机制执行login方法
    Object ob=c.newInstance();
    //调用o对象的m方法,传递"admin","123"参数,方法执行的结果是reValue
    Object reValue=m.invoke(ob, "admin","123");
    System.out.println(reValue);
 }
}

public class CustomerService {
   //登录
   public boolean login(String username,String password){
      if("admin".equals(username)&&"123".equals(password)){
       return true;
      }
      return false;
   }
   //退出
   public void logout(){
    System.out.println("已经退出系统");
   }
}

 

posted @ 2016-12-28 16:45  爱笑的berg  阅读(535)  评论(0)    收藏  举报