------- android培训、java培训、期待与您交流! ----------
1、静态导入
import static语句导入一个类中的某个静态方法或所有静态方法;
import static java.lang.Math.*;
2、可变参数
解决一个方法接收不固定个数参数的问题;
int add(in x,int... args){}
3、增强for循环
for(type 变量名:集合变量名){}
4、基本数据类型的自动装箱与拆箱
装箱:Interger num = 12;
拆箱:Syso(num+12);
5、枚举
枚举为什么会成为JAVA里面的一种规范呢?
因为就像我们每个人都有每个人自己的习惯一样,为了提高程序的效率或者编写方便,JAVA就把这种类似的规范里面的最好的提取出来写进API。
枚举就相当于一个类,编译之后会产生.class文件,其中也可以定义构造方法、成员变量、普通方法和抽象方法;
关键字enum;
枚举只有一个成员时,就可以作为一种单例形式存在;
6、反射
JAVA中反射就是把JAVA身上的每一个成分解析成一个类;
写程序的时候并不知道需要调用某个对象的哪个方法,程序运行才知道。
动态获取的信息以及动态调用对象的方法的功能称为JAVA语言反射机制;
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class();
Class cls3 = Class.forName("java.lang.String");
Constructor类代表某个类中的一个构造方法;
Field类代表某个类中的一个成员变量;
Method类代表某个类中的一个成员方法;
反射可以用于集合框架之中,可以用于替换或者屏蔽敏感词汇等
类有很多成员组成:字段、方法、构造方法、main()
1、反射类的构造函数Construtor
2、反射类的方法Method
3、反射类的main()方法
4、反射类的字段Field
7、ArrayList和HashSet的比较
ArrayList是以数组为存储结构的集合;
HashSet则是没有存储编号及顺序的。
8、资源文件
用类的加载器的方式管理资源和配置文件
9、内省和JAVABean
开发框架通常需要使用JAVA对象的属性来封装程序的数据。
内省访问JavaBean属性一:通过PropertyDescriptor类操作Bean的属性;
内省访问JavaBean属性二:通过introspector类获得Bean对象的BeanInfo,然后通过BeanInfo来获取属性的描述器(PropertyDeacriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后通过反射机制来调用这些方法。
10、泛型(编译期)
1.可以统一集合中的数据类型
1、定义在类上。
2、当方法操作的引用数据类型不确定时,定义在方法上
3、静态方法上的泛型:静态方法无法访问类上定义的泛型。如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。
4、定义在接口上
11、注解
publicclassAnnotationTest {
@SuppressWarnings("deprecation")//告诉编译器不提示过期
//注解,告诉编辑器某种信息,一个注解就是一个类
publicstaticvoidmain(String[] args) {
System. runFinalizersOnExit(true);//javac 编译时会提示过期
AnnotationTest. sayHello();
}
@Deprecated//过时了
publicstaticvoidsayHello (){
System.out.println("hi,传智播客");
}
}
格式:public @interface 类名{}
把注解加载一个类上:
@类名
public class AnnotationTest{};
可以利用反射测试MainCalss的定义上是否有某注解:
AnnotationTest.class.isAnnotationPresent( ItcastAnnotation.class)
@Retention元注解:注解的生命周期,有三个值:@RetetionPolicy.SOURCE;@RetetionPolicy.CLASS;@RetetionPolicy.RUNTIME;
@Target元注解:注解的保留位置,可以是数组方式,值例:ElementType.TYPE
可以为注解增加属性:可以使数组类型的、枚举类型、注解类型等
自定义注解类:ItcastAnnotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.itcast.day1.EnumTest;
//元注解 说明注解的生命周期 内存运行阶段
//值有三种:RetentionPolicy.RUNTIME,RetentionPolicy.CLASS,RetentionPolicy.SOURCE
@Retention(RetentionPolicy.RUNTIME)//默认在class阶段
//@Target(ElementType.METHOD)//把注解保留在方法上
//class的父是type
@Target({ElementType.METHOD,ElementType.TYPE})//把注解保留在方法上或者类上
public @interface ItcastAnnotation {
//为注解添加属性
String color() default "blue";
String value();
int[] arrayAttr() default {3,4,5};
EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.GREEN;
MetaAnnotation annotationAttr() default @MetaAnnotation("sssss");
Class a();
}
测试类:AnnotationTest
@ItcastAnnotation(a=String.class,annotationAttr=@MetaAnnotation("zzz"),color="red",value="123",arrayAttr=1)
//@ItcastAnnotation("xsd")//只有value属性需要设置的时候,才可以直接
publicclassAnnotationTest {
@SuppressWarnings("deprecation")//告诉编译器不提示过期
//注解,告诉编辑器某种信息,一个注解就是一个类
//@ItcastAnnotation("xsd")
publicstaticvoidmain(String[] args) {
System. runFinalizersOnExit(true);//javac 编译时会提示过期
AnnotationTest.sayHello();
//如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){
// 如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
ItcastAnnotationannotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
System.out.println(annotation);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arrayAttr().length);
System.out.println(annotation.lamp());
System.out.println(annotation.lamp().nextLamp().name());
System.out.println(annotation.annotationAttr().value());
System.out.println(annotation.a());
}
}
@Deprecated//过时了
publicstaticvoidsayHello (){
System.out.println("hi");
}
}
12、类加载器
1.类加载器基础知识
类加载器的作用就是获取.class里面的内容等等
java虚拟机中的三个类加载器:BootStrap,ExtClassLoader,AppClassLoader
类加载器也是java类,因为其他是java类的类加载器本身也是要被类加载器加载的,只有BootStrap不是java类,它嵌套在java虚拟机的内核中。
2.类加载器之间的父子关系和管辖范围
3.类加载器的委托机制
首先当前线程的类加载器去加载线程中的第一个类。
如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。
还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类。
每个类加载器加载类时,又先委托给其上级类加载器。
当所有父类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundException,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那有多个儿子,找哪一个呢?
对着类加载器的层次结构图和委托加载原理,解释先前将ClassLoaderTest输出成jre/lib/ext目录下的itcast.jar包中后,运行结果为ExtClassLoader的原因。
加载类的方式:
一、用当前线程的类加载器加载了线程中的第一个类,然后这个类引用到的其他类,那么那个类也用这个线程的这个类加载器进行加载。
二、可以直接调用ClassLoader.loadClass()方法来指定某个类加载器加载类。
三、每个类加载器加载类的时候,会先委托给上级类加载器,会从BootStrap开始查看这个类是否已经加载过,如果父类加载器没有加载过这个类,那么才会顺着继承关系逐级下来进行查看。
可以写一个java.lang.String类通过自己写的类加载器加载,但是这个类加载器就不是依托与虚拟机加载类了。因为如果依托于java虚拟机加载的话,java虚拟机中的类加载机制是委托机制,即最后会从BootStrap开始逐级查找要进行加载的类,如果在父类中先找到了这个类,java虚拟机就会加载这个类,那么我们写的这个类就根本不可能加载到。
数组类的
4.
自定义的类加载器必须继承ClassLoader
模板方法设计模式:loadClass:
通过findClass方法按照委托机制查找对应的类,在通过父类加载器检查所请求的类后,如果找到了类,那么就立刻调用defineClass把找到的字节码转换为这个类的实例。
如果经过父类的加载器检查所请求的类却没有找到,反而在自定义的类加载器中找到了这个类,那么就会通过自定义的类加载器中复写过的findClass来对类的字节码进行在操作,
然后调用defineClass把找到的字节码转换为这个类的实例。
A.
loadClass方法,不能覆盖 Class<?>
loadClass(String name) 使用指定的类名来加载类。 protected
Class<?> loadClass(String name, boolean resolve) 使用指定的二进制名称来加载类。 B.
findClass方法,需要覆盖这个方法。该方法按照委托机制查找对应的类,在通过父类加载器检查所请求的类后,此方法将被 loadClass 方法调用 protected
Class<?> findClass(String name) 使用指定的二进制名称查找类。
13、代理
AOP(Aspect
可以采用将切面代码移动到原始方法的周围,
这与直接在方法中编程切面代码的运行效果是一样的。
1.proxy类:
构造方法:
protected
Proxy(InvocationHandler h)
使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。
方法:
static
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。 static
Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) 返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。 static
InvocationHandler getInvocationHandler(Object proxy) 返回指定代理实例的调用处理程序。 static
boolean isProxyClass(Class<?> cl) 当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
2.InvocationHandler接口
Object invoke(Object proxy, Method method, Object[] args) 在代理实例上处理方法调用并返回结果。 这个方法的proxy就是InvocationHandler所属于的代理对象,method就是代理对象调用的方法,args就是代理对象调用的方法里面的参数。在invoke内部,menthod会调用invoke方法作用于目标对象身上。目标对象即target。
3.创建动态代理类的方法
以Collection接口的动态代理类为例
A.使用Proxy.getProxyClass(ClassLoader
loader, Class<?>... interfaces)方法来获取动态代理类的class,然后在调用这个class的构造方法Proxy(InvocationHandler h)创建实例。【期间通过反射获取构造方法。】 Collection
proxy= (Collection)Proxy.getProxyClass(Collection.class.getClassLoader,Collection.class).getConstrctor(InvocationHandler.class).newInstance(new InvocationHandler(){ public
Object invoke(Object target,Method method,Object paraListOfMethod[]){} })
B.使用Proxy.newProxyInstance(ClassLoader
loader, Class<?>[] interfaces, InvocationHandler h) 方法来直接创建动态代理类的实例 Collection
proxy= (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader, Collection.class, new InvocationHandler(){ public
Object invoke(Object target,Method method,Object paraListOfMethod[]){} })
怎样将目标类传入代理的Invoke方法中?
把target和系统代码[即我们要在方法前或后面执行的代码]封装成对象,抽到InvocationHandler外面,之后通过参数的方法传递进去。getProxy(tarket,advice)
InvocationHandler类里面只复写了Object里面的equals,toString,hashCode方法。没有复写getClass方法,所以想要获取代理类代理的目标的类名是需要自己复写getClass方法的。
代理的运作其实还是用到了反射的原理。
C.
defineClass方法将一个 byte 数组转换为 Class 类的实例。这种新定义的类的实例可以使用 Class.newInstance 来创建 protected
Class<?> defineClass(String name, byte[] b, int off, int len) 将一个 byte 数组转换为 Class 类的实例。 protected
Class<?> defineClass(String name, byte[] b, int off, int len, ProtectionDomain protectionDomain) 使用可选的 ProtectionDomain 将一个 byte 数组转换为 Class 类的实例。 protected
Class<?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain) 使用可选的 ProtectionDomain 将 ByteBuffer 转换为 Class 类的实例。 D.
ClassLoader类 protected
ClassLoader() 创建一个新的类加载器,将该加载器作为父类加载器。 protected
ClassLoader(ClassLoader parent) 使用指定的、用于委托操作的父类加载器创建新的类加载器。