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