黑马训练营----------------- Class类

---------------------- ASP.Net+Android+IO开发S.Net培训、期待与您交流! ----------------------/*
 * 一 Class
 *  1 Class(反射的基石):众多java类的共同点,他就代表的是内存里,或者他的实例对象就是内存里的字节码文件。
 * 2 字节码
 *  ----字节码:一个趔被加载到内存里面后所占用的空间里的内容就是字节码
 *  Person p1=new Person();
 *  --得到Person字节码的两种方式 Person.class/p.getClass();
 *  ---得到类的字节码的3种方式
 *   a:类名.class。
 *   b: 类的对象.getClass().
 *   c: Class.forname("classname") //静态方法,
 *    1:如果这个类已经被加载到内存里面了,直接返回字节码。
 *    2:如果类没有被加载到内存里面,先有加载器去加载,然会在返回加载进来的字节码。
 * 3 九个预定义的Class实例对象。
 *  其中8个基本类型和一个void类型对象。(Class cl=void.class();)
 *  Class.isPrimative()判断是非是一个原始类型。
 *  注:int.class==Integer.TYPE;
 *   char.class==Character.TYPE;
 * 4 数组类型的Class实例对象
 *
 * 二 反射()
 * 1 反射就是把java类中各种成分编写为一个java类。比如说一个类的方法就用相应的反射API类的对象来表示。(反射也就是利用
 * 各个java类的各个成分的的对象来完成我们需求。)
 * */
public class ClassDemo {
 
 
 public static void mehted_1()throws Exception {
  String str=new String("bh");
  
  Class cl1=String.class;
  Class cl2=str.getClass();
  Class cl3=Class.forName("java.lang.String");
  System.out.println(cl1==cl2);//true
  System.out.println(cl2==cl3);//true   结论:同一个类的字节码是相同的。
  
  System.out.println(char.class==Character.TYPE);//true;基本数据类型;
  
 }
 public static void methed_2()throws Exception{//构造方法的反射应用。
  Constructor[] con=Class.forName("java.lang.String").getConstructors();//获取String类型的字节码文件,
  //然后在获取他的所有的构造方法。
  for(Constructor c:con){
   System.out.println(c.getName().toString());//java.lang.String
  }
  Constructor con2=Class.forName("java.lang.String").getConstructor(byte[].class);//怎么获取指定
  //构造函数的够造方法。但是在jdk1.5之前,这个getConStructor(),里面要想接受可变参数的类型时,必须把这可变参数个数
  //和类型定义在一起,组成一个数组。
  System.out.println("返回的构造方法是什么"+con2.getName());
  
  //获取一个字符串的构造函数。
  Constructor  con3=String.class.getConstructor(StringBuffer.class);
  //利用构造方法去获取对象
  String str2=(String) con3.newInstance(new StringBuffer("abc") );//为什么要强转为String,印在在编译时期
  //还不知道这个构造方法是String类型,注:一定记住编译和运行的关系,在编译时只看代码的定义,不管代码的执行,如在这个
  //里面他只知道con3是一个构造方法,对他属于什么类型去只有到执行完上面一句代码以后,就是是运行时才知道这类型。
  //String str3=con3.newInstance("abc"); //Type mismatch:类型不匹配,这个报错为什么编译能够通过,而在运行
  //时才报警,这个地方的构造方法只能够接收StringBuffer
  
  
  //Class.newInstance(),newInstance()和new 的区别。
 
 
 
 //field 字段,(类里面的成员变量方法)
 ReflactPoint field=new ReflactPoint(3,5);
 Field fie= field.getClass().getField("y");
 //注:这个地方的fie的值不是5,这个变量不是对象上的,而是类上的。
 int num=(Integer) fie.get(field);//得到fie这个字段在field对象上的值。
 System.out.println(num);
 //Field fie1= field.getClass().getField("x");//NoSuchFieldException:因为这个x是私有的。
 
 Field fie2=field.getClass().getDeclaredField("x");//把这个私有的字段设置为可见的,
 //int num2=(Integer)fie2.get(field);//java.lang.IllegalAccessException,非法访问,虽然上面改为了可见的,但是还是
 //不能够访问。
 

 fie2.setAccessible(true);//把fiel字段设置为可以看见的。
 int num3=(Integer)fie2.get(field);//同个以上两个方法的修饰,这个私有的字段也能够被访问了。
 System.out.println(num3);
 }
 public void change()throws Exception{//把ReflactPoint类中的所有的String类型的字段中的b换为a,
  //思路:先获取String类型字段的集合,在对集合进行遍历。
  
  ReflactPoint rp=new ReflactPoint(3,5);
  Field[] field=ReflactPoint.class.getFields();
  
  for(Field fs:field){
   //if(fs.getType().equals(String.class)){}为什么此处不能用equals来比较,是因为比较的都是同一份字节码,用equals的语义不准确。
      if(fs.getType()==String.class){
    
    String oldValue=(String)fs.get(rp);//获取对象的String类型的字段
    //IllegalArgumentException:曾经由于传递参数错误,而导致的。
    String newValue=oldValue.replace('b', 'a');//更换掉b字符。
    fs.set(rp,newValue);//把替换后的值返回去
    System.out.println(fs);
    System.out.println(fs.toString());
 
   }
  }
  System.out.println(rp);}
 
 public static void methed_3()throws Exception{//成员方法的反射。注:由于成员方法是作用与对象的,所以一定的的Mehtoh一定是有对象作为参数。
  String str="bhjkluh";
  Method md=String.class.getMethod("replace", CharSequence.class,CharSequence.class);//得到方法的字节码。
  String[] args={"b","a"};
  String Str1=(String)md.invoke(str, args);//Invoke(对象,参数),这是按1.4方法来调用的,因为传递的参数是一个数组,在1.5版本的是可变参数
  //这就是是方法对象的方法。例如列车司机停火车,
  //Invoke(null,args),说名这是一个静态方法的对象,
  System.out.println(Str1);
 }
 public static void methodMain(){//main方法的反射。编写一个类,能够根据提供的main方法,
  // 一Arguement.main(new String[]{"a","b","c"});//用普通方法条用Arguement的主函数。(由于其是静态的有类名调用。)
  
 
 }
 public static void arrayDemo(){//数组反射的应用
 /* //特点:相同类型的相同维度的数组字节码是同一个。
  int[] arr1=new int[]{1};
  int[] arr2=new int[]{2};
  int[][] arr3=new int[2][3];
  String[] str4=new String[3];
  System.out.println(arr2.getClass() == arr1.getClass());//true
 // arr2.getClass() == arr1.getClass();// 报错:The left-hand side of an assignment must be a variable
  System.out.println(arr1.getClass().getName());//class [I
  System.out.println(arr1.getClass().getSuperclass().getName());//得到父类的名字
  Object obj1=arr1;//Object[] obj4=arr1;注意连个的区别。
  Object[] obj2=str4;
  Object[] obj3=arr3;
  
  
  //取出数组里面的元素,用的是arrays的asList(),
  System.out.println(Arrays.asList(obj1));//[[I@1bc4459]
  System.out.println(Arrays.asList(obj2));//[null, null, null]
  //为什么打印的都是都转换为了List但是结果却不一样,是由于1.4与1.5的asList方法接受的参数类型不一样,1.4 asList(Object[] obj)
  //1.5 asList(T/Object t)
  
  */
  
  Object[] obj5=new Object[]{1,2,3,4};//怎么获取数组元素的类型。
  System.out.println(obj5.getClass().getName());
  System.out.println(obj5[0].getClass().getName());//获取元素的类型
 }
 public static void PrintObject(Object obj ){//获取一个对象的具体内容,注:要有一种思想,我不知道这歌Object是什么类型
  Class cl=obj.getClass();
  if(cl.isArray()){//判断这个Class对象是不是数组类型。
   int len=Array.getLength(obj);
   for(int x=0;x<len;x++){
    
   System.out.println(Array.get(obj,x));
  }}
   else
    System.out.println(obj);
 }
 
 public static void main(String[] args)throws Exception {
  methodMain();
  // 一Arguement.main(new String[]{"a","b","c"});//用普通方法条用Arguement的主函数。(由于其是静态的有类名调用。)
  
  String startingClassName=args[0]; //ArrayIndexOutOfBoundsException:是由于我们在编译的时候没有传值所导致的。方式
  Method mainMethod=Class.forName(startingClassName).getMethod("main",String[].class);
  //mainMethod.invoke(null,new String[]{"1","2","3"});//方法对象去调用方法类的一个方法。
  //java.lang.IllegalArgumentException: wrong number of arguments::原因main方法接收的是一个String[],但是收到的确实3个。
  //其实我们传递的是一个String[]的数组,只不过是jdk1.5为了兼容1.4的特性,当我们传递一个String[]的数组他会对其拆包,可以用一下两种方法对其解决。
  mainMethod.invoke(null,new Object[]{new String[]{"1","2","3"}});//为什么我们在这个main方法中能够传递的一个Object[].
  mainMethod.invoke(null,(Object)new String[]{"1","2","3"});//强转为Object以后等于是给的事一个对象,不是一个数组,那他就不再拆包了,其实都是由于
  //jdk的方法他会对数组进行拆包,因为,1.4以前的方法接受的参数是不可变的,为了应用就把参数装进一个数组里面,在运行是在打开。
 // arrayDemo();
  
 }
 
}
class Argument//创建一个类,用来练习main方法的反射。怎么利用运行对话框
{
 public static void main(String[] args){
  for(String  str:args){
   System.out.println(str);
  }
 }
 
}

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值