Java基础增加 二


 

Java基础增加二

 

 

枚举

      为什么要有枚举

              问题:要定义星期几或性别的变量,该怎么定义?假设1-7分别表示星期一到星期日,但有人可能会写成int weekday = 0;

       枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。

 

模拟枚举示例:

// 定义一个类来模拟枚举

publicabstractclass WeekDay {

 

   private WeekDay() {}

  

   publicstaticfinal WeekDayMON =new WeekDay(){

 

      @Override

      public WeekDay nextDay() {

        returnTUR;

      }

   };

   publicstaticfinal WeekDayTUR =new WeekDay(){

 

      @Override

      public WeekDay nextDay() {

        returnWEN;

      }

   };

   publicstaticfinal WeekDayWEN =new WeekDay(){

 

      @Override

      public WeekDay nextDay() {

        returnnull;

      }

   };

  

   publicabstract WeekDay nextDay();

  

   //重写toString方法

   public String toString() {

      returnthis ==MON ?"MON" : (this ==TUR) ?"TUR":(this ==WEN) ?"WEN" :null;

   }

}

 

// 枚举

publicclass EnumTest {

 

   publicstaticvoid main(String[] args) {

     

      WeekDay weekDay = WeekDay.MON;

     

      System.out.println(weekDay.nextDay());

   }

}

 

真正的枚举示例:

// 枚举

publicclass EnumTest {

 

   publicstaticvoid main(String[] args) {

     

      WeekDay weekDay2 = WeekDay.FRI;

      //枚举默认输出元素名字

      System.out.println(weekDay2);

      //得到枚举元素的名字

      System.out.println(weekDay2.name());

      //查看本元素在所有枚举元素的位置

      System.out.println(weekDay2.ordinal());

      //把一个字符串变成所表示的枚举类型

      System.out.println(WeekDay.valueOf("SUN"));

      //把所有的枚举元素变为数组

      System.out.println(WeekDay.values().length);

   }

  

   // 真正的枚举自动帮我们实现了toString方法

   publicenum WeekDay {

      SUN,MON,TUE,WED,THI,FRI,SAT

   }

}

 

带构造方法的枚举:

publicenum WeekDay {

      //所定义的别的东西需要在元素之后并且最后一个元素加分号

      //在元素后带括号可以指定构造方法

      SUN(1),MON,TUE,WED,THI,FRI,SAT;

      private WeekDay() {

        System.out.println("first");

      }

      private WeekDay(int day) {

        System.out.println("second");

      }

   }

我试了一下,貌似不管元素后的括号里带什么数字,它都调用第二个构造方法,我写了第三个构造方法结果还是如此。不知道内部到底是怎么写的。

 

带抽象方法的枚举:

publicenum TrafficLamp {

      RED(30) {

        @Override

        public TrafficLamp nextLamp() {

           returnGREEN;

        }

      },GREEN(45) {

        @Override

        public TrafficLamp nextLamp() {

           returnYELLOW;

        }

      },YELLOW(5) {

        @Override

        public TrafficLamp nextLamp() {

           returnRED;

        }

      };

      publicabstract TrafficLamp nextLamp();

      privateinttime;

      private TrafficLamp(int time) {

        this.time = time;

      }

   }

当枚举只有一个成员时,可以用来当作单例的一种实现方式。

 

反射

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

      反射的基石——>Class

       示例代码如下:

// 反射

publicclass ReflectTest {

 

   publicstaticvoid main(String[] args)throws ClassNotFoundException {

     

      String str1 = "abc";

      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);

     

      //cls1是不是基本类型

      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());

     

   }

}

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[]void。然后可以调用一些方法,如isPrimitive()可以查看它是不是基本类型。

 

Constructor类:

    Constructor类代表某个类中的一个构造方法

得到某个类所有的构造方法:

例子Constructor[] constrctors = Class.froName(“java.lang.String”).getConstructors();

得到某一个构造方法:

    例子:Constructor constructor = Class.forName(“java.lang.String”)

           .getConstructor(StringBuffer.class);

           // 获取方法时要用到类型

创建实例对象:

    通常方式: String str = new String(new StringBuffer(“abc”));

    反射方式:String str = (String)constructor.newInstance(new StringBuffer(“abc”));

           // 调用获得的方法时要用到上面相同类型的实例对象

Class.newInstance()方法:

    例子String obj = (String)Class.forName(“java.lang.String”).newInstance();

    该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

    该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。

 

Field类:

    Field类代表某个类啵的一个成员变量

    演示:

// 演示用

publicclass ReflectPoint {

 

   privateintx;

   publicinty;

  

   public ReflectPoint(int x,int y) {

      super();

      this.x = x;

      this.y = y;

   }

  

}

// 反射

publicclass ReflectTest {

 

   publicstaticvoid main(String[] args)throws Exception{

     

      ReflectPoint pt1 = new ReflectPoint(3, 5);

      Field fieldY = pt1.getClass().getField("y");

      //fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值

      System.out.println(fieldY.get(pt1));

     

     

       Field fieldX = pt1.getClass().getDeclaredField("x");

      //启用暴力反射,私有的也能访问

      fieldX.setAccessible(true);

      System.out.println(fieldX.get(pt1));

   }

}

如果是私有的需要用getDeclaredField()去访问,然后再开启暴力反射。

 

对字节的比较用==来。因为只存在一份。

 

成员变量反射综合案例:

把字符串变量中的所有’b’改为’a’

publicclass ReflectPoint {

 

   public Stringstr1 ="ball";

   public Stringstr2 ="basketball";

   public Stringstr3 ="funfang";

  

   @Override

   public String toString() {

      returnstr1 +":" +str2 + ":" +str3;

   }

}

publicclass ReflectTest {

 

   publicstaticvoid main(String[] args)throws Exception{

     

      changeCharValue(pt1);

      System.out.println(pt1);

     

   }

 

   privatestaticvoid changeCharValue(ReflectPoint pt1)throws Exception {

 

      Field[] fields = pt1.getClass().getFields();

      for (Field field : fields) {

        //判断成员变量的类型是不是String

        if (field.getType() == String.class) {

           String oldValue = (String) field.get(pt1);

           StringnewValue = oldValue.replace('b','a');

           field.set(pt1, newValue);

        }

      }

   }

}

 

 Method类:

       Method类代表某个类中的一个成员方法

得到类中的某一个方法:

       例子:Method charAt = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);

调用方法:

       通常方法:System.out.println(str.charAt(1));

       反射方式:System.out.println(charAt.invoide(str, 1));

              如果传递给Method对象的invoke()方法的第一个参数为null,这胡着什么样的意义呢?说明该Method对象对应的是一个静态方法!

 

 

-----------------未完待续---------------------

你可能感兴趣的:(java,exception,String,Class,Constructor)