黑马程序员---Java高新技术学习笔记-1

------- android培训java培训、期待与您交流! ---------- 

1.枚举

枚举是JDK1.5出现的新特性,其实就是一个特殊的类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。枚举元素必须位于方法体中最开始的部分,枚举元素列表需要用分号和其他成员分隔。把枚举重的成员方法或变量等放在枚举元素的前面,编译器会编译失败。

用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能。首先要有私有的构造方法,每个元素分别都是一个公有的静态成员变量表示,可以有若干公有方法或抽象方法。这是带构造方法的枚举, 构造方法必须定义成私有的,枚举元素MON和MON()的效果一样,都是调用默认的构造方法。如果希望元素调用带有参数的构造函数初始化,可以在元素名后面加上参数。带方法的枚举可以通过定义枚举TrafficLamp这个例子来验证,实现普通的next方法, 实现抽象的next方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义。增加上表示时间的构造方法。具体实现代码如下:

本人比较懒,把两个例子写到一个里去了~~

[java]  view plain copy print ?
  1. <span style="font-size:12px">public class EnumTest  
  2. {  
  3.     public static void main(String[] args)  
  4.     {  
  5.         /*对应WeekDay01中的注释部分 
  6.         WeekDay01 weekDay = WeekDay01.MON; 
  7.         System.out.println(weekDay.nextDay()); 
  8.         */  
  9.           
  10.         /* 
  11.         WeekDay weekDay02 = WeekDay.FRI; 
  12.         System.out.println(weekDay02); 
  13.         System.out.println(weekDay02.name()); 
  14.         System.out.println(weekDay02.ordinal());//所在位置的index 
  15.         System.out.println(weekDay02.getClass()); 
  16.         System.out.println(WeekDay.valueOf("SUN").toString()); 
  17.         System.out.println(WeekDay.values().length); 
  18.         */     //  
  19.               //  
  20.              //  
  21.     }       //   
  22.        //\\//  
  23.     public enum WeekDay  
  24.     {  
  25.         //均为静态变量  
  26.         SUN,MON(1),TUE(1),WED,THU(1),FRI,SAT;//元素类表必须置于所有方法之上,  
  27.         //如果列表后边有内容最后需要加分号,如果没有可不加。  
  28.         //加括号是为了调用有参数的构造方法  
  29.         private WeekDay()//只能是私有类型的构造函数  
  30.         {  
  31.             System.out.println("first");  
  32.         }  
  33.           
  34.         private WeekDay(int day)  
  35.         {  
  36.             System.out.println("second");  
  37.         }  
  38.     }  
  39.       
  40.     public enum TrafficLights  
  41.     {  
  42.         //new一个子类的实例对象<RED>,并且调用父类(TrafficLights)有参数的  
  43.         //构造方法private TrafficLights(int time)<(30)>  
  44.         RED(30)  
  45.         {  
  46.             public TrafficLights nextLamp()  
  47.             {  
  48.                 return GREEN;  
  49.             }  
  50.         } ,   
  51.         GREEN(45)  
  52.         {  
  53.             public TrafficLights nextLamp()  
  54.             {  
  55.                 return YELLOW;  
  56.             }  
  57.         } ,   
  58.         YELLOW(5)  
  59.         {  
  60.             public TrafficLights nextLamp()  
  61.             {  
  62.                 return RED;  
  63.             }  
  64.         };  
  65.         public abstract TrafficLights nextLamp();   
  66.         private int time;  
  67.         private TrafficLights(int time)  
  68.         {  
  69.             this.time = time;  
  70.         }  
  71.     }  
  72.       
  73.       
  74. }</span>  
[java]  view plain copy print ?
  1. public abstract class WeekDay01  
  2. {  
  3.     private WeekDay01(){}//私有的构造方法  
  4.       
  5.     public final static WeekDay01 SUN = new WeekDay01()  
  6.     {   //匿名内部类  
  7.         public WeekDay01 nextDay()//覆盖父类的方法  
  8.         {  
  9.             return MON;  
  10.         }  
  11.     };  
  12.     public final static WeekDay01 MON = new WeekDay01()  
  13.     {   //匿名内部类  
  14.         public WeekDay01 nextDay()  
  15.         {  
  16.             return SUN;  
  17.         }  
  18.     };  
  19.       
  20.     /*对应EnumTest中注释部分 
  21.     public final static WeekDay TUE = new WeekDay(); 
  22.     public final static WeekDay WED = new WeekDay(); 
  23.     public final static WeekDay THE = new WeekDay(); 
  24.     public final static WeekDay FRI = new WeekDay(); 
  25.     public final static WeekDay SAT = new WeekDay(); 
  26.      
  27.     public WeekDay nextDay() 
  28.     { 
  29.         if(this == SUN) 
  30.         { 
  31.             return MON; 
  32.         } 
  33.         else 
  34.         { 
  35.             return SUN; 
  36.         } 
  37.     } 
  38.     */  
  39.       
  40.     public abstract WeekDay01 nextDay();//因为是抽象方法,所以其所在的类也必需要变成是抽象的  
  41.       
  42.     public String toString()  
  43.     {  
  44.         return this==SUN?"SUN":"MON";  
  45.     }  
  46.       
  47. }  

2.反射

反射就是把Java类中的各种成分映射成相应的java类。
例如:一个java类用一个Class类的对象来表示,一个类的组成部分:成员变量,方法,构造方法,包等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等
信息,这些信息就是用相应类的实例对象来表示,他们是Field,Method,Constructor,Package等。

Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有着不同的属性值。java程序中的各个java类,它们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?这个类的名字就是Class,要注意与小写class关键字的区别。

字节码:当在源程序中用到了Person这个类的时候,首先要从硬盘上把这个类的二进制代码加载到内存中,才能去创建一个个的对象,当程序中用到了多个类时候,内存中就会有多个相应的字节码,每一个字节码就是Class的实例对象总之,只要是在源程序中出现的类型,都有各自的Class实例对象。 

Person p1 = new Person();
Person p2 = new Person();

Class cls1 = Date.class(内存中)Date类字节码1;
Class cls2 = Person.calss(内存中)Person类字节码2;
 
获取字节码的方式(3种)
1.对象.getClass() 比如p1.getClass() / new Date().getClass()
2.Class.forName("java.lang.String")-->静态方法
<两种情况>1.此类的字节码已经加载到内存中了,用时可直接返回
2.此类的字节码还没有加载到内存中,便用类加载器将其加载到内存中缓存起来
 3.类名.class 比如System.class

有关以上内容的一些具体实现代码:

[java]  view plain copy print ?
  1. <span style="font-size:14px">import java.lang.reflect.*;  
  2. //import java.lang.reflect.Field;  
  3. //import java.lang.reflect.Method;  
  4.   
  5. public class ReflectTest  
  6. {  
  7.     public static void main(String[] args) throws Exception  
  8.     {  
  9.         String str1 = "abc";  
  10.         Class cls1 = str1.getClass();  
  11.         Class cls2 = String.class;  
  12.         Class cls3 = Class.forName("java.lang.String");  
  13.         System.out.println(cls1==cls2);  
  14.         System.out.println(cls2==cls3);  
  15.         System.out.println(cls1==cls3);  
  16.           
  17.         //System.out.println(cls1.toString());  
  18.         System.out.println(cls1.isPrimitive());//判断是否是基本类型的字节码  
  19.         System.out.println(int.class.isPrimitive());//int型为基本类型的字节码  
  20.         System.out.println(int.class==Integer.class);//int和Integer的类型不同  
  21.         System.out.println(int.class==Integer.TYPE);  
  22.         System.out.println(int[].class.isPrimitive());//数组不是原始类型  
  23.         System.out.println(int[].class.isArray());  
  24.           
  25.         /*================================华丽的分割线====================================*/  
  26.           
  27.         //new String(new StringBuffer("abc"));  
  28.         //新new一个对象,调用了StringBuffer构造方法  
  29.         //用反射的方式实现形同的效果  
  30.           
  31.         Constructor constructor1 = String.class.getConstructor(StringBuffer.class);  
  32.           
  33.         //Constructor类型的对象,此句中的StringBuffer表示选择哪种构造方法  
  34.         //constructor1此时只是一堆存在内存中没有实例化的二进制代码  
  35.         //(String类中StringBuffer构造方法的字节码),下一条语句才会进行实例化  
  36.           
  37.         String str = (String)constructor1.newInstance(new StringBuffer("abc"));  
  38.           
  39.         //此句中的StringBuffer表示用此构造方法是需要传一个StringBuffer进去  
  40.           
  41.         /* 
  42.          * 泛型的应用省去了类型转换之苦 
  43.         Constructor<String> cons = String.class.getConstructor(StringBuffer.class); 
  44.         String strr = cons.newInstance(new StringBuffer("abcd")); 
  45.         */  
  46.           
  47.         System.out.println("str:"+str);  
  48.         System.out.println(str.charAt(1));  
  49.           
  50.         Object obj = constructor1.newInstance(new StringBuffer("abc"));  
  51.         System.out.println("obj:"+obj);  
  52.         System.out.println(obj.toString());  
  53.           
  54.         /*================================华丽的分割线====================================*/  
  55.         /*//成员变量的反射 
  56.          * Field类代表某一个类中的一个成员变量 
  57.          * 以下代码对应ReflectPoint.java文件 
  58.          */  
  59.         ReflectPoint pt1 = new ReflectPoint(3,5);  
  60.         Field fieldY = pt1.getClass().getField("y");//只用于可见变量  
  61.         //此时fieldY只是代表一个实例化的变量,不代表一个具体的值  
  62.         //也就是说他不是对象身上的变量,而是类上的变量,需要实例化才有值  
  63.         System.out.println(fieldY.get(pt1));  
  64.         //需要用get方法来获取指定变量的值  
  65.         Field fieldX = pt1.getClass().getDeclaredField("x");//可见变量和非可见变量均可  
  66.         fieldX.setAccessible(true);//暴力反射  
  67.         System.out.println(fieldX.get(pt1));  
  68.           
  69.         /*================================华丽的分割线====================================*/  
  70.         //成员变量的反射  
  71.         changeStringValue(pt1);  
  72.         System.out.println("pt1:"+pt1);  
  73.           
  74.         /*================================华丽的分割线====================================*/  
  75.           
  76.         //成员方法的反射  
  77.         //利用反射的方法调用字符串中的字符  
  78.         Method methodCharAt = String.class.getMethod("charAt" , int.class);  
  79.         //调用Str1.charAt(1)中的字符b  
  80.         System.out.println(methodCharAt.invoke(str1 , 1));  
  81.         System.out.println(methodCharAt.invoke(null , 1));//若第一个参数为null,说明该方法为静态  
  82.         //按照JDK 1.4 version的方法调用str1中的字符c  
  83.         //Object[]{2}) object类型的数组,里面只有一个Integer对象2,数组长度为1  
  84.         System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//JDK 1.4 version  
  85.           
  86.         /*================================华丽的分割线====================================*/  
  87.         //用反射方式执行某个类中的main方法,为什么?  
  88.           
  89.         //CodeSegment  
  90.         /* 
  91.         String startingClassName = args[0]; 
  92.         Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); 
  93.         mainMethod.invoke(null, new String[]{"111","222","333"}); 
  94.         调用此段代码是会出现参数个数不对的异常,原因是new String[]{"111","222","333"}在JDK1.5+ 
  95.         中为了兼容JDK1.4,JVM在接受此数组是默认为object的数组,进行拆包从而不会当成一个参数, 
  96.         此数组会被打开数组中的元素分别作为一个参数,从而有三个参数 
  97.         解决办法: 
  98.         1.再次打包 
  99.         new Object[]{new String[]{"111","222","333"}} 
  100.         即使String数组被打开,仍然是一个Object数组 
  101.         2.(Object)new String[]{"111","222","333"} 
  102.         对编译器指明此参数为一个对象,而不是数组,不需要进行拆包 
  103.         */  
  104.           
  105.         //main方法是静态方法,不需要传递对象  
  106.         //目标:根据用户提供的类名,去执行该类中的main方法  
  107.         TestArguments.main(new String[]{"111","222","333"});  
  108.           
  109.         /*================================华丽的分割线====================================*/  
  110.           
  111.     }  
  112.   
  113.     private static void changeStringValue(Object obj) throws Exception  
  114.     {  
  115.         //将对象中所有的String类型的变量进行扫描  
  116.         Field[] fields = obj.getClass().getFields();  
  117.         //先得到obj所属的那份字节码,再得到所属的字段,对字段进行迭代  
  118.         for(Field field : fields)  
  119.         {  
  120.             //if(field.getType().equals(String.class))不建议使用  
  121.             //因为只需要得到object中String类型的字段,所以将字段中的所有元素的类型通过  
  122.             //field.getType()方法利用迭代方式逐次  
  123.             //和String类型的字节码进行比较,相同的保留,不同的舍去  
  124.             if(field.getType() == String.class)//字节码要用等号比较,专业  
  125.             {  
  126.                 String oldValue = (String)field.get(obj);//得到字段中String类型元素  
  127.                 String newValue = oldValue.replace('b''a');//将字符串中目标字符进行替换  
  128.                 field.set(obj, newValue);//将生成的新字符串赋值给obj  
  129.             }  
  130.         }     
  131.     }  
  132. }  
  133.   
  134. class TestArguments  
  135. {  
  136.     public static void main(String[] args)  
  137.     {  
  138.         for(String arg : args)  
  139.         {  
  140.             System.out.println(arg);  
  141.         }  
  142.     }  
  143. }</span>  
-------  android培训 java培训 、期待与您交流! ---------- 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值