在perference 加content Assist 可以设置快捷键
public class StaticImport { public static void main(String []args){ //int x=1; //x++; System.out.println(add(2,3)); System.out.println(add(2,3,4)); //System.out.println(Math.max(3,6)); } public static int add(int x,int ...args){ int sum=x; for(int i=0;i<args.length;i++){ sum+=args[i]; } return sum; } }
public abstract class WeekDay1 { private WeekDay1(){ } public final static WeekDay1 Sun=new WeekDay1(){ @Override public WeekDay1 nextDay() { // TODO Auto-generated method stub return Mon; } }; public final static WeekDay1 Mon=new WeekDay1(){ @Override public WeekDay1 nextDay() { // TODO Auto-generated method stub return Sun; } }; public abstract WeekDay1 nextDay(); // public WeekDay nextDay(){ // if(this==Sun){ // return Mon; // }else{ // return Sun; // } // } public String toString(){ return this==Sun?"Sun":"Mon"; } }为了更多的理解枚举,采用抽象方法定义next.day就将大量的if.else语句转移成了一个个独立的类。
package day01; import java.sql.Date; public class EnumTest { public static void main(String[] args) { WeekDay1 weekDay=WeekDay1.Mon;//赋值给引用变量 System.out.println(weekDay.nextDay()); WeekDay weekDay2=WeekDay.Fri; System.out.println(weekDay2); System.out.println(weekDay2.name()); System.out.println(weekDay2.ordinal()); //把静态的串变成枚举方法 System.out.println(weekDay2.valueOf("Sun")); new Date(300){ //调用父类的构造方法,调用有参的构造 }; } public enum WeekDay{ Sun,Mon,Tue,Fri;//相当于里面的类。如果我们写成Sun(1),可会调用第二个方法 //定义带有参数的构造方法 private WeekDay(){ System.out.println("first"); } private WeekDay(int day ){ System.out.println("second"); } } //带有抽象方法的枚举类 public enum TrafficLamp{ Red(30){//red是一个元素,它是由trafficLamp子类来实现的 public TrafficLamp nextLamp(){ return Green; } }, Green(45){ public TrafficLamp nextLamp(){ return Yellow; } }, Yellow(5){ public TrafficLamp nextLamp(){ return Green; } }; public abstract TrafficLamp nextLamp(); private int time; private TrafficLamp(int time){ this.time=time; } } }
package day01; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; public class ReflectTest { public static void main(String[] args)throws Exception { 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(cls2==cls3); //JVM中只存在一份字节码。供不同的对象调用 //String不是基本类型的字节码,它是一个类 System.out.println(cls1.isPrimitive());//isprim表示一个原始类型 System.out.println(int.class.isPrimitive()); System.out.println(int.class==Integer.class); System.out.println(int.class==Integer.TYPE);//表示包装类型的那个基本类型的字节码,所以为True System.out.println(int[].class.isPrimitive());//返回false,因为数组也是一个实例对象,用的方法是Class.isArray(); //new String(new StringBuffer("abc")); Constructor constructor1=String.class.getConstructor(StringBuffer.class);//第一个StringBuffered表示选择哪个构造方法 String str2=(String)constructor1.newInstance(new StringBuffer("abc"));//每调用一次相当于New了一次对象。第二个StringBuffered表示用这个StringBuffered传哪个对象进去。 //在编译的时候,只知道constructor1是构造方法,而不知道是哪个类下的构造方法,编译器只看变量的类型,而不看执行 System.out.println(str2.charAt(2)); //得到方法的时候需要类型,在调用方法的时候,还是要类型 ReflectPoint pt1=new ReflectPoint(3, 5); Field fieldY=pt1.getClass().getDeclaredField("y"); //FieldY的值是多少?5,错,没有对应到对象身上,Field //不代表一个具体的值,只代表一个变量,而且是字节码里面的一个变量 //它是指向哪个类身上的值 fieldY.setAccessible(true);//这里用到的是暴力反射。 System.out.println(fieldY.get(pt1)); changeStringValue(pt1); System.out.println(pt1); //直接调用,str1.charAt(1); Method methodCharAt=String.class.getMethod("charAt", int.class); //得到字节码里面的方法,再用方法去作用某个对象 System.out.println(methodCharAt.invoke(str1, 2));//args表示传几个参数。str1这个字符串身上调用charAt //invoke是方法对象身上的方法 System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//2表示一个object //这是jdk1.4里面的方法 String startingClassName=args[0]; Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class); //mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});//把三个参数包到一起传送进去 mainMethod.invoke(null,(Object)new String[]{"111","222","333"}); //每个数组的父类都是object int [] a1=new int[3]; int [] a2=new int[4]; int [][] a3=new int [2][3]; String [] a4=new String []{"a","b","c"}; System.out.println(a1.getClass()==a2.getClass()); //System.out.println(a1.getClass()==a4.getClass()); //System.out.println(a1.getClass()==a3.getClass()); Object aObj1=a1; Object aObj2=a4; //Object[] aObj3=a1;//int不是object,基本类型不是Object,基本类型的一维数组不能转成object数组 Object[] aObj4=a3;//二维是object Object[] aObj5=a4;//String是object System.out.println(Arrays.asList(a1)); System.out.println(Arrays.asList(a4));//只接受String类型,因为它是object数组 printObject(a4); printObject("xyz"); } private static void printObject(Object obj){ Class clazz=obj.getClass(); if(clazz.isArray()){ int len=Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj, i)); } }else{ System.out.println(obj); } } private static void changeStringValue(Object obj) throws Exception{ Field [] fields=obj.getClass().getFields();//得到所有的字段 for(Field field:fields){ //if(field.getType().equals(String.class)){ //对字节码的比较应该拿==相比 if(field.getType()==(String.class)){//这里应该用==,因为是同一份字节码 String oldValue=(String) field.get(obj); String newValue=oldValue.replace('b', 'a'); field.set(obj, newValue); } //这个field代表字段 } } } class TestArguments { public static void main(String[] args) { for(String arg:args){ System.out.println(arg); } } }
ReflectPoint.java
package day01; public class ReflectPoint { private int x; public String str1="ball"; public String str2="basketball"; public String str3="haha"; public int y; public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReflectPoint other = (ReflectPoint) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } @Override public String toString(){ return str1+":"+str2+":"+str3; } }
2.当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段,否则,对象修改后哈希值最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在Container方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从Hashset集合中单独删除当前对象,从而造成内存泄露。
package day01; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Properties; public class ReflectTest2 { public static void main(String[] args) throws Exception{ InputStream ips=new FileInputStream("config.properties");//这里用到的是相对路径 //现在的内容是ArrayList.所以结果是4, //如果把properties中的内容改为Hashcode,结果就变为2 //这里就用到了反射技术开发框架的原理 Properties props=new Properties(); props.load(ips); ips.close();//告诉操作系统把这个流关闭 String className=props.getProperty("className"); Collection collections=(Collection) Class.forName(className).newInstance(); //调用不带参数的构造方法 //Collection collections=new HashSet(); ReflectPoint pt1=new ReflectPoint (3,3); ReflectPoint pt2=new ReflectPoint (5,5); ReflectPoint pt3=new ReflectPoint (3,3); collections.add(pt1); collections.add(pt2); collections.add(pt3); collections.add(pt1); //pt1.y=7;//这个集合与hashcode没有关系 //collections.remove(pt1); System.out.println(collections.size()); } }
newStance(),调用不参数的构造方法