IDE ---> Itegrity Development Environment
Java EE --- > Java Enterprise Edition
Java SE ---> Java Standard Edition
反射:
反射就是把Java类中的各个组成部分映射成相应的Java类。
hashCode方法:
只有类的实例对象要被采用哈希算法进行存储和检索时,这个类才需要按要求覆盖hashCode方法。即使程序可能暂时不会用到当前类的hashCode方法,但是为它提供一个hashCode方法也不会有什么不好,没准以后什么时候又会用到这个方法了,所以,通常要求hashCode方法和equals方法一并被同时覆盖。
* 通常来说,一个类的两个实例对象用equals方法比较的结果相等时,它们的哈希码也必须相等,但反之则不成立,即equals方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象equals方法的比较结果可以不相等,例如字符串"BB"和"Aa"的equals方法比较结果肯定不相等,单他们的hashCode方法返回值却相等。
* 当一个对象被存储进HashSet以后,就不能再修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值和最初存储进HashSet中的哈希值就不同了,在这种情况下,即使在contains方法中使用该对象的当前引用作为参数去HashSet中检索对象,也将会返回找不到对象的结果,这也会导致无法从Haset集合中单独删除当前对象的引用,从而有可能会造成内存泄露。
toString方法:
返回一个对象的字符串表现形式,这个字符串也就是对这个对象的文本形式的描述
加载配置文件:
Java程序中读取配置文的相对路径相对于当前的工作目录,一般不推荐使用,而要使用类加载器的方式来获得配置文件的路径,类加载器搜索的目录为classpath所指定的目录。
// 这里的参数使用相对路径(相对于classpath目录)
InputStream is1 = ClassLoaderTest.class.getClassLoader().getResourceAsStream("com/itheima/config.properties");
URL u1 = ClassLoaderTest.class.getClassLoader().getResource("com/itheima/config.properties");
// 这里的参数可以使用绝对(相对于classpath目录)和相对路径(相对于获得ClassLoader的类的目录)
InputStream is5 = ClassLoaderTest.class.getResourceAsStream("/com/itheima/config.properties");
InputStream is6 = ClassLoaderTest.class.getResourceAsStream("config.properties");
// 这里的参数可以使用绝对(相对于classpath目录)和相对路径(相对于获得ClassLoader的类的目录)
URL u5 = ClassLoaderTest.class.getResource("/com/itheima/config.properties");
URL u6 = ClassLoaderTest.class.getResource("config.properties");
JavaBean:
* JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类的中方法主要用于访问私有的字段,且方法名符合某种命名规则。
* 如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO),这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,就是getter和setter。JavaBean中的属性是根据其中的getter和setter方法方法来确定的,而不是根据其中的成员变量。
* 一个符合JavaBean特点的类可以当做普通的类来使用,但把它当做JavaBean来用肯定会带来一个额外的好处,我们才会去了解和应用JavaBean,好处如下:
-->1.在JavaEE开发中,经常要使用到JavaBean。很多环境要求按JavaBean方式进行操作。
-->2.JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果自己去通过getXxx方法来访问私有的xxx,有一定难度,用内省这套API操作JavaBean比普通类的方式更方便。
内省--IntroSpector:
PropertyDescript/Introspector/BeanUtils
注解--Annotation:
注解相当于一种标记,加了注解就等于打上了某种标记。以后javac编译器、开发工具和其它程序可以用反射来了解你的类及各种元素上有无何种标记,如果有这种标记,就去做相应的事。注解可以加在包、类、字段、方法、方法参数、局部变量上。
JDK提供的注解:Deprecated/Overrride/SuppressWarnings………
定义一个最简单的自定义注解:public @interface MyAnnotation { }
需要注意的是这个自定义的注解也需要一个注解:@Retention元注解,用来表示自定义注解的生命周期
@Retention有三种取值:
1.RetentionPolicy.SOURCE ----> Java源文件
2.RetentionPolicy.CLASS ---> class文件
3.RetentionPolicy.RUNTIME ---> 内存中的字节码
@Target元注解用于表示自定义的注解可以用在哪些地方,通过ElementType的枚举元素来指定
泛型:
泛型指定的是未确定的"类"类型,不能使用基本数据类型做泛型的参数
限定类型,可以将集合中的元素限定为特定类型
类加载器的委托机制:
当Java虚拟机要加载一个类时,到底使用那个类加载器加载呢?
* 首先当前线程的类加载器去加载线程中的第一个类
* 如果A类中引用了B类,Java虚拟机将使用加载A类的类加载器来加载B类
* 还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载某个类
* 每个类加载器加载类时,又先委托给其上级类加载器
* 当所有祖宗类加载器没有加载到类,回到发起者类加载器,如果还加载不到,就抛出ClassNotFoundException,而不是去找发起者类加载器的子类,因为没有getChild()方法,即使有,那如果有多个子类,又该选择哪一个呢?
代理:
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理,日志,计算方法的运行时间,事务管理等等,要怎么做呢?
* 可以编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用时加上系统功能的代码。
* 如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类,切换就起来很方便,例如,想要日志功能时就配置代理类,否则就配置目标类,这样,在系统中增加和减少功能就很方便。
动态代理:
* JVM可以在运行期动态生成出类的字节码,这些动态生成的类往往被用作代理类,即动态代理类
* JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理
* CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么就可以使用CGLIB库
* 代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的4个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中
* 调用代理对象的从Object继承的hashCode(),equals(Object obj),toStirng()这几个方法时,代理对象会将调用请求转发给InvocationHandler对象,对于其它方法,则不转发调用请求,在代理类内部有自己的实现
切面编程就是将切面的代码以对象的方式封装,再传递给执行者,执行者再执行切面对象的方法,就等于执行了切面的代码
让动态生成的类称为目标类的代理:
怎样将目标传进去?
* 直接在InvocationHandler实现类中创建目标类的实例对象,可以看到运行效果和加入日志代码,但没有实际意义
* 为InvacationHandler实现类注入目标类的实例对象,不能采用用匿名内部类的形式了
* 让匿名的InvacationHandler实现类访问外面方法中的目标类实例对象的final类型的引用变量
将创建代理的过程改为一种更优雅的方式,编写一个public Object getProxy(final Object target)方法绑定接收目标同时返回代理对象,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API
将系统功能代码模块化,即将切面代码也改为通过参数形式提供,怎样把要执行的系统功能代码以参数形式提供呢?
* 把要执行的代码装到一个对象的某个方法里,然后把这个对象作为参数传递,接收者只要调用这个对象的方法,即等于执行了外界提供的代码
* 为public Object getProxy(final Object target)方法增加一个Advice(这个接口中的方法就是封装了系统的功能代码,具体功能由子类实现)参数 ---> public Object getProxy(final Object target, final Advice acvice)
这样,就可以在InvacationHandler的invoke中使用target和Advice来完成新增的系统功能了