JAVA新特性笔记


静态导入:

         JDK1.5新特性,当使用一个类的静态成员和静态方法时,为了简化语法可以使用静态导入。

         语法:import static 类.*(类.方法/变量);使用该类的静态变量时可以省略类名。

示例代码:

import static java.lang.System.*;

class Demo

{

         public static void main(String[] args)

         {

                   //打印时可以直接省略System类名。

                   out.println("ssssss");

         }

}

 

可变参数列表:

         一个方法接受的参数不固定时,可以使用可变参数列表。可变参数列表实际上是将参数列表传到数组中进行操作。

         有了可变参数,就不用显示地编写数组语法了,当你指定参数时编译器实际上会为你去填充数组,你获得的仍旧是一个数组,在每一种情况中,编译器都会使用自动包装机制来匹配重载方法。

         当传入一个数组时,编译器判断其为数组,就不会再为你填充数组。

         可以通过在某个方法中增加一个非可变参数来解决问题。

代码示例:

class Demo

{

         static void f(float i,Character ... args) {

                   Ssytem.out.println();

         }

         static void f(Character...args) {

                   System.out.println(args);

         }

         public static void main(String[] args)

         {

                   f(1,'a');

                   f('1','b');

         }

}

 

增强for循环:

         语法:for( type 变量名:集合变量名) { };

         注意事项:变量名必须在for循环内部进行定义。

                              集合变量可以是数组或是实现了Iterator借口的集合类。

 

自动装箱和自动拆箱:

Integer i = 3;//自动打包

int j = i+1;//自动拆包

         对于基本类型数据,在打包成对象时,如果数据在一个字节之内,则将其暂存起来,下次使用时直接使用。

 

枚举:

         关键字enum可以将一组具有名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用。

         除了不能继承自一个enum之外,我们基本上可以将enum看作一个常规类。

         Enum中添加构造方法和main方法:         

public enum EnumDemo {

         WEST("xi"),NORTH("bei"),SOUTH("nan"),EAST("dong");

         private String de;

         private EnumDemo(String str) {

                   de = str;

         }

         public static void main(String[] args) {

                   for(EnumDemoed : EnumDemo.values()) {

                            System.out.println(ed+" "+ed.de);

                   }

         }

}

 

注意事项:

1.        如果定义自己的方法,那么必须在enum实例序列的最后添加一个分号。

2.        在定义方法之前必须定义enum实例。

3.        我们只能在enum定义的内部使用其构造器创建enum实例。

4.        Enum的构造方法会在类加载时运行,进行其成员的初始化,enum定义结束后,编译器就不允许我们再使用其构造器来创建任何实例。

 

Switch语句中的enum:

         一般情况下我们必须使用enum类型来修饰一个enum实例,但是在case语句中不必如此。

public enum EnumDemo {

         GREEN,YELLOW,RED;

         public static void main(String[] args) {

                   EnumDemo color = EnumDemo.RED;

                   switch(color) {

                   case RED : color = EnumDemo.GREEN;

                   break;

                   case GREEN: color = EnumDemo.YELLOW;

                   break;

                   case YELLOW: color = EnumDemo.RED;

                   break;

                   }

         }

}

enum.valuse():

         values()方法是由编译器添加的static方法。

 

使用借口组织枚举:

         在一个借口内部,创建实现该接口的枚举,一次将元素进行分组,可以达到将枚举元素分类组织的目的    

public interface Food {

         enum Appetizer implements Food {

                   ASLAD,SOUP;

         }

         enum MainCourse implements Food {

         }

         enum Dessert implements Food {

         }

}

         Enum类型实现了Food接口,那么我们就可以将其 实例 向上转型为food,所以上例中的所有东西都是Food。

 

使用EnumSet替代标志:

 

反射机制:

ClassLoader类加载机制:

通过Eclipse的run dialogue 查看详细的运行过程。          Java-Verbose:class

1.        并非一次性加载。

2.        需要时进行加载(运行期间动态加载)。

Bootstrap classLoader是系统类加载器,加载系统必须的类库,没有名字。返回为NULL

Extension classLoader是扩展类加载器。

Application classLoader是自定义类加载器。

程序运行过程

 

 

Java.lang.Class类:

         Class保存的程序的字节码,当运行一个程序时,JVM虚拟机将字节码加载到内存中,Class类保存的信息:类的名字,类访问权限属性,字所属的包,字段信息,方法信息等等。

         如何得到Class:

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

2.        对象.class  例如:new String().class

3.        Class.forName(“类名的全称”)  例如:Class.forName(“java.lang.String”); 常用

java中所有的关键字,都是类,可以通过Class类取得这些。

java.lang.reflect.Constructor类:

         Constructor代表类中的构造方法。得到Constructor对象的方法:Constructor []  getConstructor(参数);

         public static void main(String[] args)throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException  {

                   Person p = new Person(1,"chenqi");                //生成一个Person对象

                   Class c = p.getClass();               //获取Person类的Class对象

                   Constructor con = c.getConstructor(int.class,String.class);          //获取带两个参数的构造方法

                   con.newInstance(1,"nihao");          //通过该构造对象生成一个对象

                   System.out.println(p);

         }

}

 

java.lang.reflect.Filed类:

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

         public static void main(String[] args)throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {

                            Person p = new Person(3,"wr23");

                            Class c = p.getClass();               //获取pClass对象

                            Field f = c.getDeclaredField("name");    //通过对象pClass对象,获取名为 name Field的对象。

                           f.set(p, "nihao");              //可以更改对象p f所指定的值。

                            System.out.println(f.get(p));            //获取值

         }

}

 

java.lang.reflect.Method类:

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

public class TestFiled {

         public static void main(String[] args)throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

                   Person p = new Person(1,"chenqi");

                   Class c = p.getClass();

                   Method m = c.getMethod("setId",int.class);

                   System.out.println(m);

                   m.invoke(p, 10);

                   System.out.println(p);

         }

}

 

javaBean

         javaBean是一个特殊的类,主要用来传递数据信息。特点:方法主要用来访问类中私有变量,符合一定的命名规则。

         简单javaBean示例:

public class Person {

         public int getId() {

                   return id;

         }

         public void setId(int id) {

                   this.id = id;

         }

         public String getName() {

                   return name;

         }

         public void setName(String name) {

                   this.name = name;

         }

         private int id;

         private String name;

}

通过内省操作javaBean:

PropertyDescriptor 描述 Java Bean通过一对存储器方法导出的一个属性。内省操作主要针对Javabean来的,简化了一系列反射的步骤;

比如反射一个方法需要首先获得字节码 class.forName();然后利用Constructor实例化,在获得method,然后在invoke这个方法;

而内省则只要一下几部即可:

PropertyDescriptor 其参数为(propertyNameobj.class) 

第一个参数是bean的名称,命名规则如下:

getName 方法的propertyNamename。说明:去掉getset修饰符剩下Name,如果第二个字母为小写则首字母也改成小写,所以最终变成name

setCPU 方法的propertyName CPU。说明:去掉getset修饰符剩下CPU,如果第二个字母为大写则所有字符不变,所以最终变成CPU

第二个参数是需要改变类的字节码。

然后getWriteMethod().invoke(obj, value)即可;

public class Test {

         public static void main(String[] args) {

                   try {

                            //生成一个PropertyDescriptor进行对javaBean的内省操作

                            PropertyDescriptor pd = new PropertyDescriptor("id", Person.class); 

                            //将某一指定属性与此特性相关联。

                            pd.setValue("id",1);

                            //获取id的值

                            System.out.println(pd.getValue("id"));

                   } catch (IntrospectionException e) {

                            e.printStackTrace();

                   }

         }

}

 

注解:(新特性)

Annotaticon:

         Annotation表示的是一种注释的语法,在java最早的程序中提倡的是程序与配置代码分离,最新的理论是将所有的配置写入到代码之中。

JDK提供的三个内建注解:

@Deprecated

@Deprecated注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器只会发出警告

Override

表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。保证正确的复写操作。保存范围Runtime

SuppressWarnings

表示压制警告,使不出现警告信息。SuppressWarnings类中有一个valuse的数组字段,所以SuppressWarnings可以同时压制多个警告信息。

格式:SuppressWarnings(“ ” , ” ”);或者 SupressWarnings(values= (“ ” , ” ”) );

注解结构图:

自定义Annotation:

    定义Annotation的语法:public @interface Annotaticn的名称

    使用Annotation的语法:在同一包下 @Annotaticn的名称

使用String

//自定义的Annotation

public @interface MyAnnotation {

    //添加两个字段,并设置默认值。

    public String key() default "nihao";     

    public String value() default "nimei";

}

 

@MyAnnotation (key="nihao",value="nimei")   //这里的值可以设定,不进行设定将取默认值

public class Test {

}

使用枚举限定Annotation的取值。

public @interface MyAnnotation {

    public String key() default "nihao";     

    public String value() default "nimei";

    //设置枚举属性,它的取值仅限定在枚举类型可以提供的几个

    public Color color() default Color.RED;

public String str [];  //可以使用数组进行操作,如果只往数组传入一个值,可以直接写 str=” ”

MyAnnotation ma = @MyAnnotation(value=””); //使用Annotation设置属性

}

//枚举

public enum Color {

    RED("红色"),GREEN("绿色"),YELLOW("黄色");

    private String info;

    Color(String arg0) {   

        this.info = arg0;

    }

}

//实现

@MyAnnotation (key="nihao",value="nimei",color=Color.GREEN)//这里的值可以设定,不进行设定将取默认值

public class Test {

}

 

Retention和RetentionPolicy:(源注解)

    java.lang.annotation包中定义了所有的与Annotation的操作。全部继承自Annotation接口。

    Retention本身是一个Annotation,指示注释类型的注释要保留多久。其中的取值通过RetentionPolicy这个枚举类型指定的范围。如果注释类型声明中不存在Retention 注释,则保留策略默认为 RetentionPolicy.CLASS

    三个范围:

1.  只在源码中起作用:public static final RetentionPolicy SOURCE

2.  只在编译后的class文件中起作用:public static final RetentionPolicy CLASS

3.  在程序运行期间起作用:public static final RetentionPolicy RUNTIME(可以反射读取)。

注意:只有在Runtime范围内的Annotation才能被用户获取。

//自定义的Annotation

@Retention(value = RetentionPolicy.RUNTIME //修饰自定义的Annotation,表示Runtime范围

public @interface MyAnnotation {

}

 

反射与Annotation:

    Annotation要起作用必须与反射机制相结合。通过反射可以取得在一个方法上声明的全部Annotation内容。

    在Field、Method、Constructor的父类上提供了与Annotation操作的方法:

1.   获取全部的Annotation:public <T extendsAnnotation> T getAnnotation(Class<T> annotationClass)

2.   判断操作的是否是指定的Annotation:public booleanisAnnotationPresent(Class<? extends Annotation> annotationClass)

获取方法上的Annotation:

public class Test {

    @Override

    @Deprecated

    @SuppressWarnings(value="1")

    public String toString() {

        return "hello world";

    }

    public static void main(String[] args) throws NoSuchMethodException, SecurityException {

        Class c = Test.class;

        Method m = c.getMethod("toString");

        for(Annotation m1 : m.getAnnotations()) {

            System.out.println(m1); //@java.lang.Deprecated()

        }

    }

}

 

深入Annotation:

    Java.lang.annotation下的 Target 、Documented、Inherited

 

Target: 限制Annotation的使用范围。可以使用多个限定范围

 

Documented :指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。

 

Inherited :表示当前Annotation可以继承。

 

泛型深入:

    泛型是提供给javac编译器使用的,可以限定集合中的元素的类型,让编译器挡住非法输入,在生成的字节码文件中会去除这些类型信息,所以使用 getClass();获得的和原始类型相同。

    参数化类型与非参数化类型兼容:

        Collection<String> c = new List();

        Collection c = new List<String>();

    参数化类型与非参数化类型不存在继承:

       Collection<Object>c = new ArrayList<String>();//错误

 

代理:

    代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 

       要点:实现同一个接口,代理类调用和目标类相同的方法,并提供其他服务。

       重要原则:不要把供货商暴漏给用户。

 

静态代理:

//目标类

public class Tank {

         void start() {

                   System.out.println("运行");

         }

}

//代理类

public class Test {

         Tank t;

         Test (Tank tank) {

                   t = tank;

         }

         void start() {

                   System.out.println(System.currentTimeMillis());

                   t.start();

                   System.out.println(System.currentTimeMillis());

         }

}

动态代理:

JVM可以在运行期动态生成类的字节码,这种动态生成的类往往被用作动态代理类。

JVM生成的动态类必须实现一个或多个接口,所以动态代理类只能用作具有相同接口的目标类。

JDK Complier, CGLIB ASM 库可以为没有实现接口的类生成一个子类,一个该类子类也可以作为该类的代理。

模拟 JDK 动态代理:

package com.bjsxt.proxy;

 

 

public class Client {

    public static void main(String[] args) throws Exception {

        Tank t = new Tank();

        InvocationHandler h = new TimeHandler(t);

       

        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class, h);

       

        m.move();

    }

}

//可以对任意的对象、任意的接口方法,实现任意的代理

 

package com.bjsxt.proxy;

 

public interface Moveable {

    void move();

   

}

 

 

package com.bjsxt.proxy;

 

import java.util.Random;

 

 

public class Tank implements Moveable {

 

    @Override

    public void move() {

       

        System.out.println("Tank Moving...");

        try {

            Thread.sleep(new Random().nextInt(10000));

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

       

    }

 

   

   

}

 

package com.bjsxt.proxy;

 

import java.lang.reflect.Method;

 

public interface InvocationHandler {

    public void invoke(Object o, Method m);

}

 

 

package com.bjsxt.proxy;

 

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

 

public class TimeHandler implements InvocationHandler{

   

    private Object target;

 

 

 

    public TimeHandler(Object target) {

        super();

        this.target = target;

    }

 

 

 

    @Override

    public void invoke(Object o, Method m) {

        long start = System.currentTimeMillis();

        System.out.println("starttime:" + start);

        System.out.println(o.getClass().getName());

        try {

            m.invoke(target);

        } catch (Exception e) {

            e.printStackTrace();

        }

        long end = System.currentTimeMillis();

        System.out.println("time:" + (end-start));

    }

 

}

 

//生成代理的类

package com.bjsxt.proxy;

 

import java.io.File;

import java.io.FileWriter;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

import java.net.URL;

import java.net.URLClassLoader;

 

import javax.tools.JavaCompiler;

import javax.tools.StandardJavaFileManager;

import javax.tools.ToolProvider;

import javax.tools.JavaCompiler.CompilationTask;

 

public class Proxy {

    public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception { //JDK6 Complier API, CGLib, ASM

        String methodStr = "";

        String rt = "\r\n";

       

        Method[] methods = infce.getMethods();

        /*

        for(Method m : methods) {

            methodStr += "@Override" + rt +

                         "public void " + m.getName() + "() {" + rt +

                            "   long start = System.currentTimeMillis();" + rt +

                            "   System.out.println(\"starttime:\" + start);" + rt +

                            "   t." + m.getName() + "();" + rt +

                            "   long end = System.currentTimeMillis();" + rt +

                            "   System.out.println(\"time:\" + (end-start));" + rt +

                         "}";

        }

        */

        for(Method m : methods) {

            methodStr += "@Override" + rt +

                         "public void " + m.getName() + "() {" + rt +

                         "    try {" + rt +

                         "    Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +

                         "    h.invoke(this, md);" + rt +

                         "    }catch(Exception e) {e.printStackTrace();}" + rt +

                       

                         "}";

        }

       

        String src =

            "package com.bjsxt.proxy;" +  rt +

            "import java.lang.reflect.Method;" + rt +

            "public class $Proxy1 implements " + infce.getName() + "{" + rt +

            "    public $Proxy1(InvocationHandler h) {" + rt +

            "        this.h = h;" + rt +

            "    }" + rt +

           

           

            "    com.bjsxt.proxy.InvocationHandler h;" + rt +

                           

            methodStr +

            "}";

        String fileName =

            "d:/src/com/bjsxt/proxy/$Proxy1.java";

        File f = new File(fileName);

        FileWriter fw = new FileWriter(f);

        fw.write(src);

        fw.flush();

        fw.close();

       

        //compile

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);

        Iterable units = fileMgr.getJavaFileObjects(fileName);

        CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);

        t.call();

        fileMgr.close();

       

        //load into memory and create an instance

        URL[] urls = new URL[] {new URL("file:/" + "d:/src/")};

        URLClassLoader ul = new URLClassLoader(urls);

        Class c = ul.loadClass("com.bjsxt.proxy.$Proxy1");

        System.out.println(c);

       

        Constructor ctr = c.getConstructor(InvocationHandler.class);

        Object m = ctr.newInstance(h);

        //m.move();

 

        return m;

    }

}

 

 

    

 


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值