Java 反射 视频学习

高新技术视频17-27,主要内容包括:

反射的概念,Constructor、Field 、Method 的反射,

对接收数组参数的成员方法的反射,数组与Object的关系及其反射类型,

数组的反射应用,框架的概念及用反射技术开发框架的原理。
(包括ReflecTest.java,ReflectPoint.java,ReflectTest2.java3个部分的代码:

 

 /*
 * 1,Constructor 构造方法的反射,2,Field 成员变量的反射,3,Method 方法的反射,
 * 4,对接收数组参数的成员方法进行反射,5,数组与Object的关系及其反射类型
 * 6,得到数组里面的元素列表,7,数组反射
 * 随后 反射的综合案例 Rdflect2.java
 */
package cn.itcast.day1;

import java.lang.reflect.*;
import java.util.Arrays;


public class ReflectTest {
 
 public static void main(String[] args) throws Exception {
  
  String str1 = "abc";
  //str1的3份字节码  
  Class cls1 = str1.getClass();
  Class cls2 = String.class;
  Class cls3 = Class.forName("java.lang.String");
  System.out.println(cls1 == cls2);
  System.out.println(cls1 == cls3);
  
  System.out.println(cls1.isPrimitive()); //基本类型
  System.out.println(int.class.isPrimitive());
  System.out.println(int.class == Integer.class);
  System.out.println(int.class == Integer.TYPE);
  System.out.println(int[].class.isPrimitive());
  System.out.println(int[].class.isArray());//判断class是否是数组类型
  
  String.class.getConstructor(StringBuffer.class);//可变参数
  //new String(new StringBuffer("abc"));实例 instance
  Constructor constructor1 =String.class.getConstructor(StringBuffer.class);//类型  运行的时候才知道是String
  String str2 = (String)constructor1.newInstance(/*"abc"*/new StringBuffer("abc"));//同样类型的对象
  System.out.println(str2.charAt(2));
  
  //Field 成员变量的反射:
  ReflectPoint pt1 = new ReflectPoint(3,5);
  Field fieldY = pt1.getClass().getField("y");
  //fieldY的值是多少? 是5,错! fieldY不是对象身上的变量,而是类上,要用它去取某个对象身上取对应的值.
  System.out.println(fieldY.get(pt1));
  Field fieldX = pt1.getClass().getDeclaredField("x");//declared 声明的
  fieldX.setAccessible(true);  //暴力反射  Accessible可见的
  System.out.println(fieldX.get(pt1));
  
  changeStringValue(pt1);//为什么这里会出错呢  不是object 类型么    原因 是因为  导入了  import org.omg.CORBA.Object;
  System.out.println(pt1);
  
  //Method 成员方法的反射:
  //str1.charAt(1);   circle.draw();
  Method methodCharAt = String.class.getMethod("charAt", int.class);
  System.out.println(methodCharAt.invoke(str1, 1)); //在str1对象身上调用,invoke是方法对象methodCharAt的方法. 
        //面向对象的思想,
//  System.out.println(methodCharAt.invoke(null, 1));//说明method对象的方法是静态方法,不需要对象就可以调用
  System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//1.4的语法调用
  
  
  //TestArguments.main(new String[]{"111","222","333"});  一般的调用
  String startingClassName = args[0];
  Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);//接受一个参数  -String数组
//  mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});//不当作一个数组 当作三个参数
  mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
  
  int [] a1 = new int []{1,2,3};
  int [] a2 = new int [4];
  int [][] a3 = new int [2][3];
  String [] a4 = new String[]{"a","b","c"};
  System.out.println(a1.getClass() == a2.getClass());
//  System.out.println(a1.getClass() == a4.getClass());
//  System.out.println(a1.getClass() == a3.getClass());
  System.out.println(a1.getClass().getName());
  System.out.println(a1.getClass().getSuperclass().getName());
  System.out.println(a4.getClass().getSuperclass());
  
  Object aObj1 = a1;
  Object aObj2 = a4;
//  Object[] aObj3 = a1;   //基本类型不是Object
  Object[] aObj4 = a3;
  Object[] aObj5 = a4;
  
  System.out.println(a1);
  System.out.println(a4);
  System.out.println(Arrays.asList(a1));//输出 [[I@14318bb] int类型数组,不符合1.4,在1.5中就当作一个object
  System.out.println(Arrays.asList(a4));//String数组  当作多个元素
  
  //Object obj = null ;
  printObject(a4);
  printObject("xyz");
  
 }
 
 //如果是数组就把里面的元素一个个打印出来,不是数组就直接打印对象
 private static void printObject(Object obj) {
  Class clazz = obj.getClass();
  if(clazz.isArray()){
   int len = Array.getLength(obj);
   for(int i=0;i<len;i++){
    System.out.println(Array.get(obj, i));
   }
   
  }else{
   System.out.println(obj);
  }  
 }

 private static void changeStringValue(Object obj) throws Exception {
  
  Field[] fields = obj.getClass().getFields();//得到所有字段
  for(Field field : fields){
   //if(field.getType().equals(String.class)); 字节码用等号比较
   if(field.getType() == String.class){ //得到字段的类型  等于String 类型
    String oldValue = (String)field.get(obj);
    String newValue = oldValue.replace('b', 'a');
    field.set(obj, newValue);//(对象 , 值)
   }
  }
  
 }

}
//对接收数组参数的成员方法进行反射
//用反射方式执行 main 方法 ,
//为什么要用反射的方式去调用  写程序的时候不知道执行哪一个类
class TestArguments{
 public static void main(String[] args){
  for(String arg : args){
   System.out.println(arg);
  }
 } 
}
/* 25~ 对数组进行反射  
 length  int[0]  获取数组里面的值,设置数组的值
 Object[] a = new Object[]("a",1);
 a[0].getClass().getName();   只能得到每一个具体的元素的类型  不能得到整个数组的类型.
*/

 

 

package cn.itcast.day1;

public class ReflectPoint {
 private int x ;
 public int y ;
 public int getX() {
  return x;
 }

 public void setX(int x) {
  this.x = x;
 }

 public int getY() {
  return y;
 }

 public void setY(int y) {
  this.y = y;
 }

 public String str1 = "ball";
 public String str2 = "basketball";
 public String str3 = "itcast";
 public ReflectPoint(int x, int y) {
  super();
  this.x = x;
  this.y = y;
 }
 
 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + x;
  result = prime * result + y;
  return result;
 }

 
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  ReflectPoint other = (ReflectPoint) obj;
  if (x != other.x)
   return false;
  if (y != other.y)
   return false;
  return true;
 }

 @Override
 public String toString(){
  return str1 + ":" + str2 + ":" + str3;
 }
}

package cn.itcast.day1;

import java.io.*;
import java.util.*;

public class ReflextTest2 {
/*
26~
  ArrayList有序 可重复,HashSet,无序,不可重复,先判断有没有相等(equals方法)的对象,再放入.
   将集合分成若干个存储区域,每个对象可以计算出一个哈希吗,可以将哈希码分组,
   每组分别对应某个存储区域,根据对象的哈希吗
 
    如果两个对象的equals对象相等,就要让它们的hashcode值相等,为了让相等的对象不重复.
   
 
      只有类的实例对象要被采用哈希算法进行存储和检索的时候,这个类才需要按照要求覆盖hashCode
      方法.虽然程序可能暂时不会用到当前类的hashCode方法,但是为它
      提供一个hashCode方法也不会有什么不好,可能以后就能用到这个方法,
      所以,通常要求hashCode方法的和equals方法一并被同时覆盖.
 
      内存泄漏问题.
27~
 反射的作用-实现框架功能
 工具类被用户调用,框架调用用户提供的类
28~
 用类加载器的方式管理资源和配置文件
 getRealPath();//金山词霸/内部
 一定要用完整的路径,但完整的路径不是硬编码,而是运算出来的
*/
 public static void main(String[] args) throws Exception {
  
//  InputStream ips = new FileInputStream("config.properties"); 配置内容
  
//  InputStream ips = ReflextTest2.class.getClassLoader().getResourceAsStream
//          类           类加载器  
//  ("cn/itcast/day1/config.properties");
  
  InputStream ips = ReflextTest2.class.getResourceAsStream("config.properties");
  
  Properties props = new Properties();
  props.load(ips);
  ips.close();//处理Windows 系统物理资源,  ips由java虚拟机管理
  String className = props.getProperty("className");
  Collection collections = (Collection)Class.forName(className).newInstance();
//                 不带参数的构造方法
//  Collection collections = new HashSet();
  ReflectPoint  pt1 = new ReflectPoint(3,3);
  ReflectPoint  pt2 = new ReflectPoint(5,5);
  ReflectPoint  pt3 = new ReflectPoint(3,3);

  collections.add(pt1);
  collections.add(pt2);
  collections.add(pt3);
  collections.add(pt1);
  
  
  pt1.y = 7;       //改变了hashcode的值 ,
  collections.remove(pt1);
  System.out.println(collections.size());
 }

}
 

 

 

 

展开阅读全文

没有更多推荐了,返回首页