黑马程序员 Java高新技术1

来源:互联网 发布:wtf什么意思网络用语 编辑:程序博客网 时间:2024/05/29 18:57

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

 

可变参数的特点:

1.只能出现在参数列表的最后。

2."..."位于变量类型和变量名之间,前后无空格都可以。

3.调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。

public class VarableParameter {public static void main(String[] args) {System.out.println(add(2,3));System.out.println(add(2,3,4));}public static int add(int x,int... args){int sum=x;for(int i=0;i<args.length;i++){sum+=args[i];}return sum;}}

增强for循环:

格式:for(type 变量名:集合变量名){...}

注意:迭代变量必须在()中定义。集合变量可以是数组或实现了Iterable接口的集合类。

还以上面例子来写:

public class VarableParameter {public static void main(String[] args) {System.out.println(add(2,3));System.out.println(add(2,3,4));}public static int add(int x,int... args){int sum=0;for(int arg:args){sum+=arg;}return sum;}}

享元模式(flyweight):有很多小的对象,他们有很多属性相同把他们变成一个对象,那些不同的属性把他们变成方法的参数成为外部状态,那些相同的成为内部状态。

Integer对象在-128-127之间会缓存在池中

class AutoBox {public static void main(String[] args) {Integer iObj=3;System.out.println(iObj+3);Integer i1=13;Integer i2=13;Integer i4=128;Integer i5=128;System.out.println(i1==i2);System.out.println(i4==i5);}}

结果:15  true false

枚举:

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

如何实现枚举:

1.私有构造函数。

2.每个元素分别用一个公有的静态成员变量表示。

3.可以有若干公有方法或抽象方法。

public abstract class WeekDay1 {      public final static WeekDay1 SUN = new WeekDay1(){          public WeekDay1 nextDay() {              return MON;          }             };            public final static WeekDay1 MON = new WeekDay1(){          public WeekDay1 nextDay() {              return SUN;          }             };            private WeekDay1(){}      public abstract WeekDay1 nextDay();      public String toString(){          return this == SUN?"SUN":"MON";           }  }  
public class EnumTest {public static void main(String[] args) {//WeekDay1 weekDay = WeekDay1.MON;//System.out.print(weekDay.nextDay());WeekDay weekDay2 = WeekDay.FRI;//System.out.println(weekDay2);System.out.println(weekDay2.name());System.out.println(weekDay2.ordinal());   //获取FRI在枚举中的位置System.out.println(WeekDay2.valueOf("SUN"));System.out.println(WeekDay.values().length);   //获取枚举内的所有元素并返回数组}//带有构造方法的枚举public enum WeekDay{SUN(1),MON(),TUE,WED,THI,FRI,SAT;    private WeekDay(){System.out.println("first");}    private WeekDay(int i){System.out.println("second");}}}

枚举相当于一个类,其中可以定义构造方法、成员变量、普通方法和抽象方法。

枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后面要有分号与其他成员分隔.把枚举中的成员方法或变量等放在枚举元素的前面,编译器会报告错误。

构造方法必须定义成私有。

枚举的元素是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义。

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

public class EnumTest2 {public static void main(String[] args) {}public enum Trafficlamp{RED(30){public Trafficlamp nextTra() {return GREEN;}},GREEN(45){public Trafficlamp nextTra() {return YELLOW;}},YELLOW(5){public Trafficlamp nextTra() {return RED;}};public abstract Trafficlamp nextTra();private int time;private Trafficlamp(int time){this.time=time;}}}


反射的基石--Class类:

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型。

如何得到字节吗对应的类:

1.类名.class,例如:System.class

2.对象.getClass().例如:new String().getClass()
3.Class.forName("类名"),例如:Class.forName("java.util.Date")

九个预定义Class实例对象

boolean, byte, char, short, int, long, float,double, void

通过字节码.isPrimitive() 方法来判断是否是基本数据类型。

基本数据类型包装类的常量TYPE代表所包装的基本数据类型字节码。例如:int.class==Integer.TYPE的结果为true。

数组类型的Class实例通过 字节码.isArray() 来判断是否为数组

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

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

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

例: Constructor[] constructors = Class.forName("java.lang.String").getConstructors()。

得到某一个构造方法:

例:Constructor[] constructors = Class.forName("java.lang.String").getConstructors(StringBuffer.class).

创建实例对象:

通常方式:String str = new String(new StringBuffer("asd")).

反射方式: String s = (String)constructor.newInstance(new StringBuffer("abc"))。

Class newInstance()方法

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

import java.lang.reflect.Constructor;public class ConstructorDemo {      public static void main(String[] args) throws Exception{                        Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);            String str = constructor.newInstance( new StringBuffer("abc"));            System. out.print(str.charAt(2));      }}


Fisld类:

代表某个类中的一个成员变量。

如何获取对象的成员变量对象:

 Field filedX = 对象.getClass().getField("变量名")。

这里,如果成员变量为私有的,那么需要用以下方法:

 Field filedX = 对象.getClass().getDeclaredField("变量名")。

不过这里还不可以对私有变量进行操作,需要用到setAccessible(true)方法,暴力获取。

import java.lang.reflect.Field;class ReflectPoint{      private int x;      public int y;      public ReflectPoint( int x, int y) {             super();             this. x = x;             this. y = y;      }}class FieldDemo{      public static void main(String[] args) throws Exception{            ReflectPointt rp = new ReflectPoint(3,5);            Field fieldY = ReflectPoint. class.getField( "y");            System. out.println(fieldY);             System. out.println(fieldY.get(rp));                                     Field fieldX = WhyNot. class.getDeclaredField( "x");            System. out.println(fieldX);//5            fieldX.setAccessible( true); //设置变量x为可访问            System. out.println(fieldX.get(rp)); //3                }}

更改变量的值:

import java.lang.reflect.Field;/*把字符串中的'b'换成'a'.*/class TestString{      public String str1 = "ball";      public String str2 = "basketball";      public String str3 = "itcast";      }public class FIeldTest {      public static void main(String[] args) throws Exception {            TestString ts = new TestString();             //获取所有变量,返回Field数组            Field[] fields = ts.getClass().getFields();             //高级for循环遍历             for(Field field : fields){                   //判断变量类型是否为String                   if(field.getType() == String. class){                         //向下转型为String类型                        String oldValue = (String)field.get(ts);                         //调用String类中的replace方法                        String newValue = oldValue.replace( 'b', 'a');                         //把修改后的字符串重新赋值给 ts对象的变量                        field.set(ts, newValue);                        System. out.println(field.get(ts));                  }            }      }}

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

得到类中的某一个方法:

Method charAt = Class.forName("java.lang.String").getMethod("charaAt",int.class).

调用方法例:

charAt.invoke(str , 1)。

这里要说明一点:如果传递给Method对象的invoke()方法的对象参数是null , 说明该Method方法是一个静态方法。

import java.lang.reflect.Method;public class MethodDemo {      public static void main(String[] args) throws Exception{            String str = "abc";            Method md = String. class.getMethod( "charAt", int. class);            System. out.println(md.invoke(str, 1));            System. out.println(md.invoke(str, new Object[]{2}));      }}

反射中main方法(静态)的调用:

import java.lang.reflect.Method;public class MethodTest {      public static void main(String[] args) throws Exception{            String startingClassName = args[0];            Method mainMethod = Class.forName(startingClassName).getMethod( "main", String[]. class);             //两种方式来调用静态main方法            mainMethod.invoke( null, new Object[]{ new String[]{"aa","bb" ,"cc" }});             //mainMethod.invoke(null, (Object)new String[]{"aa","bb","cc"});      }}class TestArguments{      public static void main(String[] args){             for(String arg : args){                  System. out.println(arg);            }      }}

数组的反射:

1.具有相同维数和元素类型的数组属于同一个Class类型 , 具有相同的Class实例对象。

2.代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class。

3.基本类型的一维数组可以被当成Object类型使用 , 不能当作Object[]类型使用 ; 例如 : int[]可以是Object , 但不能是Object[] ; 非基本类型的一维数组 ,既可以当作Object类型使用 , 又可以当作Object[]类型使用。

4.Arrays.asList()方法处理int[]和String[]时的差异:int[]被当成一个Object元素存进集合 , String[]被当成一个Object[]数组 , 数组的元素被拆开后存进集合。

部分代码:

int [] a1=new int[3];int [] a2=new int[4];int [][] a3=new int[2][3];String [] a4=new String[3];System.out.println(a1.getClass()==a2.getClass());System.out.println(a1.getClass()==a4.getClass());System.out.println(a1.getClass()==a3.getClass());System.out.println(a1.getClass().getName());System.out.println(a1.getClass().getSuperclass().getName());System.out.println(a4.getClass().getSuperclass().getName());

结果:true  false  false  [I  java.lang.Object   java.lang.Object

例2:

import java.lang.reflect.Array;public class Test {      public static void main(String[] args) {            String[] strs = new String[]{ "a", "b"};            String str = "xy";                        printObject(strs);            printObject(str);      }            public static void printObject(Object obj){             Class c = obj.getClass();            System. out.println(c.getName());             if(c.isArray()){                   int len = Array. getLength(obj);                   for( int x = 0; x < len; x++){                   System. out.println(Array. get(obj, x)); //用Array类中的get()方法遍历出数组中的元素                  }            }             else                  System. out.println(obj);      }}

关于集合中HashSet的一点注意:当一个对象被存储进HashSet集合中已后,就不能修改这个对象中的那些参与运算哈希值的字段了,否则,对象修改后的哈希值与最初的HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。

内省(IntroSpector)JavaBean:

JavaBean是一种特殊的Java类,主要用于传递信息,这种Java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。

规则:去掉get、set后的字母,例如,一个类有方法getAge( )和setAge( ) , 那么bean的属性为age,而不是成员变量,因为成员变量是private看不见的。

获得属性名的规则:如果属性名的第二个字母是小写,则把第一个字母小写。例如,gettime—>time,setTime—>time,getCPU—>CPU。



 

 

原创粉丝点击