黑马程序员___ 基础加强篇(一)

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


一、从基本数据的自动装箱,来说一说享元模式

看到张老师视频的11集,说道了这么一段代码:

 

public class AutoBox {

public static void main(String[] args) {

Integer i1 = 13;

Integer i2 = 13;

System.out.println(i1 == i2);

} }

当然将13这个int基础类型的数据赋值给Integer基础类型包装类,这个过程进行的自动装箱。这是JDK1.5的新特性(自动装箱和拆箱)
额,这个自然明白,一开始觉得既然自动装箱,当然要在堆内存中new 两个对象了,来装两个13,但是心里也感觉有点浪费空间,后来打印
System.out.println(i1 == i2);结果是true,还自认为他们比的是值不是地址,应该重写了equals方法,但是用的是==不是equals方法。老师说是他们放在缓冲池中,不会创建两个不同的对象,前提条件是:-128到127之间。当i1=135,i2=135时,才会有两个不同的对象,是因为不在-128到127之间,缓冲池里不存储。这就是所谓的享元模式。

也就是说java1.5将小的整数-128到127之间采用享元模式来存储到缓冲池,对于大的整数则不采用。(flyweight享元模式)

二、说一说枚举类型(JDK1.5新特性)

在jdk1.5之前,没有枚举类型,想实现枚举,用的是抽象类实现。

package com.heima;

public class EnumTest {  public static void main(String[] args) {   System.out.println("星期天的下一天是:"+WeekDay.SUN.nextDay().toString());   System.out.println("星期天的下一天是:"+WeekDay.SUN.nextDay());  } }

/**  * 没有枚举之前,在jdk1.5之前,用的是抽象类。  * @author ming  *  */ abstract class WeekDay {  private WeekDay() {}  

//使用匿名内部类,new 抽象类  public static final WeekDay SUN = new WeekDay() {

  @Override   public WeekDay nextDay() {    return MON;   }     };    public static final WeekDay MON = new WeekDay() {

  @Override   public WeekDay nextDay() {    return SUN;   }     };    public abstract WeekDay nextDay();     /**   * 覆写toString()方法,为了方便打印输出   */  public String toString() {   return this==SUN?"SUN":"MON";  } }

输出结果:
星期天的下一天是:MON
星期天的下一天是:MON
注:采用抽象方法代替if else,改写为一个个独立的类。当然nextDay要是抽象方法。
现在用jdk1.5来使用枚举类吧。写了一个最复杂的enum。

package com.heima;

public class EnumTest2 {

 public static void main(String[] args) {   WeekDay2 wd = WeekDay2.FRI;   System.out.println(wd.name());   System.out.println(wd.ordinal());      System.out.println(WeekDay2.valueOf("WEN"));   System.out.println(WeekDay2.valueOf("WEN").toString());   System.out.println(WeekDay2.values().length);      System.out.println("-----------------");   TraficLamp tf = TraficLamp.GREEN;   System.out.println(tf.name());   System.out.println(tf.nextLamp());  }    public enum WeekDay2 {

  SUN(1),MON,TUE,WEN,THI,FRI,SAT;      private WeekDay2(){    System.out.println("first constructor");   }      private WeekDay2(int day) {    System.out.println("second constructor");   }  }    /**   * 最复杂的枚举   * @author ming   *   */  public enum TraficLamp {   RED(30) {    @Override    public TraficLamp nextLamp() {     return GREEN;    }   },GREEN(45) {    @Override    public TraficLamp nextLamp() {     return YELLOW;    }   },YELLOW(5) {    @Override    public TraficLamp nextLamp() {     return RED;    }   };   private int time;   private TraficLamp(int time) {    this.time = time;   }   public abstract TraficLamp nextLamp();  } }

 
输出结果:
second constructor
first constructor
first constructor
first constructor
first constructor
first constructor
first constructor
FRI
5
WEN
WEN
7
-----------------
GREEN
YELLOW
三、反射(JDK1.2就有了)
首先说一下Class类的概念,对文档的解释翻译一下:
Class类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class对象。基本的 Java 类型(boolean、byte、char、short、int、long、float和 double)和关键字 void也表示为 Class对象。 Class没有公共构造方法。Class对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass方法自动构造的。 
得到一个类的字节码的三种方式:

1、Class c1 = Person.class;  //代表Person类的字节码

2、Person p = new Person();

      p.getClass(); //得到他的字节码
3、Class.forName("java.lang.String"); //得到String类的字节码

注:反射的时候主要使用第三种方式,来得到类的字节码文件。

注意8个基本类型和void也是Class的对象。

如:Class c2 = void.class;

接着,说一下什么是反射,课本或者老师的讲解,就不赘述了。

一句话总结:反射就是将Java类中的各种成分映射成相应的java类。

写个简单的例子:

Constructor cons = String.class.getConstructor(StringBuffer.class);
  String obj1 = (String)cons.newInstance(new StringBuffer("abc"));
  String obj2 = (String)cons.newInstance(new StringBuffer("hin"));
  System.out.println("第一个实例:"+obj1);
  System.out.println("第二个实例:"+obj2);

注意进行类型转换。编译器只关心变量的定义,不关心语句的执行。

当然第一句,有不同的写法,forName也行。

总结一下:使用反射得到对象的过程,class--》constructor--》newInstance

Method methodCharAt = String.class.getMethod("charAt",int.class);

System.out.println(methodCharAt.invoke(obj,1));

对数组的反射,在这里 先不做说明。

把张老师java基础加强的前半部分的代码整理一下:

 

package com.heima;

import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;

public class RefectTest {  public static void main(String[] args) throws Exception {   String str1 = "abc";   Class c1 = str1.getClass();   Class c2 = String.class;   Class c3 = Class.forName("java.lang.String");      //说明不管怎么写,都是那个String类的字节码   System.out.println(c1==c2);   System.out.println(c1==c3);      //是不是8大基本类型,当然不是了false   System.out.println(c1.isPrimitive());   System.out.println(int.class.isPrimitive());      System.out.println(int.class == Integer.class);   System.out.println(int.class == Integer.TYPE);   

  Constructor cons = String.class.getConstructor(StringBuffer.class);   String obj1 = (String)cons.newInstance(new StringBuffer("abc"));   String obj2 = (String)cons.newInstance(new StringBuffer("hin"));   System.out.println("第一个实例:"+obj1);   System.out.println("第二个实例:"+obj2);      ReflectPoint pt1 = new ReflectPoint(3, 5);      Field fieldY = pt1.getClass().getField("y");   //注意fieldY不是y的值,只是代表这个类(有y的)   System.out.println(fieldY.get(pt1));   Field fieldX = pt1.getClass().getDeclaredField("x");   fieldX.setAccessible(true);//暴力反射,private修饰的x,拿不到的情况使用。   System.out.println(fieldX.get(pt1));      System.out.println(pt1);   changeStringValue(pt1);   System.out.println(pt1);      String str2 = "abde";   Method methodCharAt = String.class.getMethod("charAt", int.class);   System.out.println(methodCharAt.invoke(str2, 1));      //通常情况下使用正常方式访问 另外一个类的成员方法(这里是静态方法)   TestArguments.main(new String[] {"111","222","333"});      String startingClassName= args[0];   Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);   //注意给参数用new Object[]{}打包。   mainMethod.invoke(null, new Object[]{new String[]{"3234","324"}});     }    //使用反射更改类中属性的值(就像Spring一样)  private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {   Field[] fields = obj.getClass().getFields();   for(Field field : fields) {    if(field.getType() == String.class) {     String oldValue = (String)field.get(obj);     String newValue = oldValue.replace('a', 'g');     field.set(obj, newValue);    }   }  } }

class TestArguments {  public static void main(String[] args) {   for(String arg : args) {    System.out.println(arg);   }  } }

package com.heima;

public class ReflectPoint {  private int x;    public  int y;    public String s1 = "hellam";  public String s2 = "basketball";

 public ReflectPoint(int x, int y) {   super();   this.x = x;   this.y = y;  }

 @Override  public String toString() {   // TODO Auto-generated method stub   return s1+"--"+s2;  }   }





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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值