首页 > 代码库 > 黑马程序员——JAVA学习笔记十二(高新技术一)

黑马程序员——JAVA学习笔记十二(高新技术一)

 1,    静态导入:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.solaire.enhance;
import static java.lang.Math.max; 
//import   语句可以导入一个类或某个包中的所有类
//import static  静态导入 JDK5以后才有。语句导入一个类中的某个静态方法或所有静态方法
//无名包和有包名中的类在一起,没有package,则为无名包。
//一个类中只有一个public类,且源文件必须和类名一样,如果都没有public,则源文件名随意。
//当导入同一个类名时,
//使用无名包必须在同一个目录下。
//com.solaire.enhance.Week 有包名为主 ,则是和com.solaire.enhance.*,则是无包名为主。同时
//有包名,则要加全称路径。
public class StaticImport {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int x;
        System.out.println(max(36));
    }
 
}
,2,    可变参数与for循环增强
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class VariedParameter {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        add(1,2,3,4,5,6);
        System.out.print(add(1,2,3,4,5,6));
    }
     
//      可变参数的特点:
//      只能出现在参数列表的最后;这个要记住
//      ...位于变量类型和变量名之间,前后有无空格都可以;
//      调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
    public static int add(int ... args) {
        int sum = 0;
       for(int i = 0; i < args.length; i++) {
            sum += args[i];
        }
//         语法:
//         for ( type 变量名:集合变量名 )  { … } 
//         注意事项:
//         迭代变量必须在( )中定义!
//         集合变量可以是数组或实现了Iterable接口的集合类
       sum = 0;
        for(final int i: args){ //for高级特性
            sum += i;         //变量名:集合
        }
        return sum;
    }
 
}
3,    基本数据类型的自动拆箱与装箱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//对象包装器,Integer ,Long, Double, Float, Short, Byte,Chararter,Void, Boolean
//(前6个派生于Number类)。是不可继承类,一旦构造了包装器,就不允许更改包装器里面的值。
//装箱:XXX.valueOf() 拆箱:XXX.xxvalue(),自动装箱规范要求boolean,byte,char<= 127,
//介于-128~127之间的short 和int被包装到固定的对象中。
public class AutoBoxClass {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Integer iboj = 3//自动装箱
        int i = iboj + 1//自动拆箱
        System.out.println(i);
         
        Integer i1 = 13;
        Integer i2 = 13;// -128 ~127,因为那么小的数,会经常使用,所以会会缓存,
        System.out.println(i1 == i2);
         
        Integer i3 = 137;
        Integer i4 = 137;// 数字大,就不会缓存,每个有自己的对象
        System.out.println(i3 == i4);
        //这是一种设计模式,享元模式flyweight
        //简单才交模式,复杂就不是模式了。
         
        Integer i5 = Integer.valueOf(12);
        Integer i6 = Integer.valueOf(12);// 
        System.out.println(i5 == i6);
    }
 
}
4,    枚举
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//  枚举:枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,
//  否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序
//  中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
//  在比较两个枚举类是不用euqals,直接用==
//  可以在枚举类型中添加构造器,方法和域。构造器只是在构造枚举常量的时候被调用。
//  所有的枚举类型都是Enum类的子类,继承了这个类的很多方法。
//  常用方法: class.values()
//  Enum.valueOf(class , string)    class.valueof()  object.ordinl()
//  枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔。
//  把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。
    public enum TrafficLamp{
        RED(30){
            public TrafficLamp nextLamp(){
                return GREEN;
            }
        }, 
        GREEN(45){
            public TrafficLamp nextLamp(){
                return YELLOW;
            }
        }, 
        YELLOW(5){
            public TrafficLamp nextLamp(){
                return RED;
            }
        };
         
        public abstract TrafficLamp nextLamp();
        private int time;
        private TrafficLamp(int time){
            this.time = time;
        }
    }
 
//自己实现枚举类
public class Week {
 
    private Week() {
        // TODO Auto-generated constructor stub
    }
    public static final Week  MON = new Week();
    public static final Week  TUE = new Week();
    public static final Week  WED = new Week();
    public static final Week  THU = new Week();
    public static final Week  FRI = new Week();
    public static final Week  SAT = new Week();
    public static final Week  SUN = new Week();
     
    public Week nextDay() {
        System.out.println("******************************");
        if  (this == SAT)
            return SUN;
        else if(this == SUN  )
            return MON;
        else if(this == MON  )
            return TUE;
        else if(this == TUE )
            return WED;
        else if(this ==WED  )
            return THU;
        else if(this == THU  )
            return FRI;
        else if(this == FRI  )
            return SAT;
        else 
            return null;
 
    }
    public String toString(){
        System.out.println("****************************");
        if  (this == SAT)
            return "SAT";
        else if(this == SUN  )
            return "SUM";
        else if(this == MON  )
            return "MON";
        else if(this == TUE )
            return "TUE";
        else if(this ==WED  )
            return "WED";
        else if(this == THU  )
            return "THU";
        else if(this == FRI  )
            return "FRI";
        else
            return null;
    }
}
5,    反射
在程序运行期间,JAVA始终为所有对象维护一个被称为运行时的类型标示。保存这些信息的类称为Class,Class类代表Java类,它的各个实例对象又分别对应什么呢?
对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等。 一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码, 
不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用 一个个的对象来表示,这些对象显然具有相同的类型,这个类型是就是class类。
 
 
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
 
 
能够分析类能力的程序称为反射。反射机制可以用来:
在运行中分析类的能力
在运行中查看对象
实现通用的数组操作代码
利用Method对象,这个对象很像C++中的函数指针
 
如何得到各个字节码对应的实例对象(3种)
( Class类型) 类名.class,例如,System.class
对象.getClass(),例如,new Date().getClass()
 Class.forName("类名"),例如,Class.forName("java.util.Date");
第一种和其他两种有不同的地方,当用它创建Class对象的引用时,不会自动的初始化该class对象,为了使用类而做的准备工作实际包含了3个步骤:
1,加载:这是有类加载器执行的。该步骤将查找字节码,然后创建一个Class对象。
2,链接:在链接阶段将验证类中的字节码,为静态域分配存贮空间,并且如果有需要的话,将解析这个类创建的对其他类的引用。
3,初始化: 如果该类具有超类,对其初始化,执行静态初始化和静态初始化块
初始化被延迟到了对静态方法(构造器隐式的静态的)或者非静态域进行首次引用时。
class主要方法:
Field[] getFields() public成员     Field getField(String name)
Field[] getDeclaredFields()  全部成员     Field getDeclaredField(String name)
Constructor  Method  类似
 
getDeclareingClass()外部类
getDecEncloseingClass() 匿名外部类也可以
getClassLoader()获取加载类
getResourceAsInputStream()获取资源
 
reflect中的主要类:Constructor   Field   Method  Modifier,分别描述了类的构造器,域,和方法,标示符。
Class getDeclaringClass() 描述内部定义的类
Class[] get ExceptionTypes() (constructor 和 Methods)  描述方法抛出的异常
int  getModifiers()  返回一个用于描述修饰符的整形值
String getName()  用于返回项目名字
Class[ ] getParameterTypes()(constructor 和methods)  返回参数形参的类型数组Class对象
Class  getReturnType() (methods)  返回类型Class对象
 
static  String toString(int modifiers)  返回修饰字符串
static boolean isAbstruct(int modifiers)  
isFinal() isInterface()  isPrivate()  isNative() isProtect() isPublic() isStatic() isStrict() isSynchronized()  isVolatile()
 
AccessibleObject安全管理:上面都继承该类,暴力反射
void  setAccessible(boolean flag)  为类设置可访问标志
boolean isAccessible  返回对象的可访问标志
Static void setAccessible(AccessbleObject [] arrgy , boolean flag) 
 
反射创建数组:
Array类允许动态的创建数组,例如将这个特性应用到Array中的copyOf方法实现,应该记得这个方法可以用于扩展已经填满的数组。
Parent[] a = new Parent[100];
a = Arrays.copyOf(a, 2*a.length);
 
如何写这样一个方法?
public   static Object[] badCopyOf(Object[] a , int length) 
{
Object [] array = new Ojbect[new.length);
System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newlength);
return newArray; //运行时出错
}
可以利用反射, Object new array = Array.newInstance(componentType, newleng);
public   static Object[] badCopyOf(Object[] a , int length) 
{
Class cl = a.getClass();
if(!cl.isArray()) return null;
Class componenttype = cl.getComponentType();
int newlength = Array.getLength(a);
Object newarry = Array.newInstance(componentType, newleng);
System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newlength);
return newarray;
}
int [] a  = {1,2,3,4,5};
a = (int[] ) goodCopy(a, 10);
反射调用方法:
invoke()(method)  返回值:如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型, 
则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型, 则数组元素不被包装在对象中;换句话说,将返回基本类型的数组。
如果底层方法返回类型为 void,则该调用返回 null。
 
因为invoke参数和返回类型必须是Object类型的,意味着必须要多次进行强制转换,这样做编译器错过了检查代码的机会。所以在必要的时候再用它。
反射实现框架:
框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
 
 
6,    JavaBean内省
JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性。
 
作为一个黑盒子的模型,JavaBean有3个接口面,可以独立进行开发。
1. JavaBean可以调用的方法。
2. JavaBean提供的可读写的属性。
3. JavaBean向外部发送的或从外部接收的事件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//  采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。
//  在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法, 
//  得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。
    public static void setProperties1(ReflectPoint pt1, String propertyName,
            Object obj) throws IntrospectionException, IllegalAccessException,
            InvocationTargetException {
         
        BeanInfo ins = Introspector.getBeanInfo(pt1.getClass());
        PropertyDescriptor [] props = ins.getPropertyDescriptors();
         
        for(PropertyDescriptor pd : props) {
             
            if(pd.getName().equals(propertyName)) {
                Method method = pd.getWriteMethod();
                method.invoke(pt1, obj);
                 
            }
        }
    }
//
//  直接new一个PropertyDescriptor对象的方式来让大家了解JavaBean API的价值,
//  先用一段代码读取JavaBean的属性,然后再用一段代码设置JavaBean的属性。
    public static void setProperties(Object pt1, String propertyName,
            Object obj) throws IntrospectionException, IllegalAccessException,
            InvocationTargetException {
         
        PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
        Method methodsetX = pd.getWriteMethod();
        methodsetX.invoke(pt1, obj);
         
    }
    public static Object getProperties(Object pt1, String propertyName)
            throws IntrospectionException, IllegalAccessException,
            InvocationTargetException {
         
        PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
        Method methodgetX = pd.getReadMethod();
        Object retVal = methodgetX.invoke(pt1);
        return retVal;
         
    }
7,    beanutils工具包 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) throws Exception {
    // TODO Auto-generated method stub
    ReflectPoint pt1 = new ReflectPoint(13);
     
    BeanUtils.getProperty(pt1,"x");//return  String类型 ,BeanUtils以字符串操作
    BeanUtils.setProperty(pt1, "x""9");
    System.out.println(pt1.getX()+"......"+BeanUtils.getProperty(pt1,"x").getClass().getName());
     
    BeanUtils.setProperty(pt1, "birthday.time",4000);//属性链一级级的向下
    System.out.println(BeanUtils.getProperty(pt1,"birthday")+"..........."+
                        BeanUtils.getProperty(pt1,"birthday").getClass().getName());
     
     
    PropertyUtils.setProperty(pt1, "x"8);  //返回原始类型,PropertyUtils以原始类型操作
    System.out.println(pt1.getX());
 
}

 

黑马程序员——JAVA学习笔记十二(高新技术一)