黑马程序员_基础加强02

来源:互联网 发布:淘宝网购物蜜腊 编辑:程序博客网 时间:2024/04/30 08:56

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

 

1 对javaBean的简单内省操作

注意:选中代码,点右键--reflector(重构)--Extract Method这样会把这些代码自动抽取成为一个方法
/*
例子:用内省获取一个类的变量
*/
package cn.itcast;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class IntrospectorTest {
 public static void main(String[]args) throws IntrospectionException, IllegalArgumentException, IllegalAccessException, InvocationTargetException
 {
  ReflectPoint pt1=new ReflectPoint(3,5);
  
  String propertyName="x";
  Object retVal = getpropertyName(pt1, propertyName);
  System.out.println(retVal);
  
  Object value=7;
  setPropertyName(pt1, propertyName, value);
  
  System.out.println(pt1.getX());
 }

 private static void setPropertyName(ReflectPoint pt1, String propertyName,
   Object value) throws IntrospectionException,
   IllegalAccessException, InvocationTargetException {
  PropertyDescriptor pd2=new PropertyDescriptor(propertyName,pt1.getClass());
  Method methodSetX = pd2.getWriteMethod();
  methodSetX.invoke(pt1,value);
 }

 private static Object getpropertyName(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;
 }

}

1.2 复杂的内省操作
采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性.在程序中把一个类当作javaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息.
例子:
package cn.itcast;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class IntrospectorTest {
 
 public static void main(String[]args) throws Exception
 {
  ReflectPoint pt1=new ReflectPoint(3,5);
  
  String propertyName="x";
  Object retVal = getpropertyName(pt1, propertyName);
  System.out.println(retVal);
  
 }
 private static Object getpropertyName(Object pt1, String propertyName)
   throws Exception {
  
  BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
  PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
  Object retVal = null;
  for(PropertyDescriptor pd : pds){
   if(pd.getName().equals(propertyName))
   {
    Method methodGetX = pd.getReadMethod();
    retVal = methodGetX.invoke(pt1);
    break;
   }
  }
  return retVal;
 }

}

2 了解注解及java提供的几个基本注解(注意:这是jek1.5的新特性)
2.1) @SuppressWarnings的应用
runFinalizersOnExit(boolean flag);这个方法是已过时的,如果在类中调用了这个方法在eclipse中会有一个横线在这个方法上,表示方法已过时,如果在方法上面声明了@SuppressWarnings()方法,用命令行编译的时候就不会提示这个方法已过时,编译可以通过.  但是eclipse不会理会这个声明,runFinalizersOnExit(boolean flag)方法上依然有横线
/*
例子:@SuppressWarnings("deprecation")使用
*/
public class AnnotationTest {

 /**
  * @param args
  */
 
 @SuppressWarnings("deprecation")
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  System.runFinalizersOnExit(true);
 }

}

2.2)@Deprecated
直接在类中增加一个方法,并加上@Deprecated标注,在另外一个类中调用这个方法
/*
例子:@Deprecated的使用,在方法上面声明了@Deprecated,那么sayHell0()方法上面就会多了一条横线,表示这个方法,已过时,如果其它类调用到这个方法,那么这个方法上面就会有一条横线,表示已过时,不希望用户调用这个方法
*/
 @Deprecated
 public static void sayHello(){
  System.out.println("hi,传智播客");
 }

2.3)@Override覆盖
比如说我们定义一个类的时候,要覆盖Object类的equals方法,我们以为自己覆盖了父类的equals方法,但是实际上没有覆盖成功,但是我们就认为自己覆盖成功了,因为程序不会报错,导致找不到错误原因,为了避免这种情况,我们可以在要覆盖的方法上面,写上:@Override表示这个方法是覆盖的,如果你没有覆盖成功,程序就会提示了没有覆盖成功
/*
例子:@Override的使用
如果你写的不是Object,写成了其它类,没有覆盖成功,程序会提示
*/
@Override
public boolean equals(Object obj)
{
 return this.name==obj.name;
}

2.4)注解总结:
注解相当于一种标记,加了注解就等于打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事.标记可以加在包,类,字段,方法,方法的参数以及布局变量上
看java.lang包,可看到jek中提供的最基本的annotation

2.5)注解的定义与反射的调用
定义一个最简单的注解:public @interface MyAnnotation{}
把它加在某个类上:
@MyAnnotation
public class AnnotationTest{}

2.5.1)根据反射进行测试AnnotationTest的定义上是否有@MyAnnotation
根据反射测试的问题,引出@Retention元注解的讲解,其三种取值:
RetetionPolicy.SOURCE,RetetionPolicy.Class,RetetionPolicy.RUNTIME
分别对应:java源文件,class文件,内存字节码文件
@Override和@SuppressWamings注解只在源文件中存在,因为javac编译后@Override就没有用途了
@Deprecated注解在字节码文件中保留,因为你要把这个类加载到内存中,你才能够得到这个类的方法,然后在判断这个方法是否过期,所以保留在字节码文件时期

2.5.2)例子:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
//@Target({ElementType.METHOD,ElementType.TYPE})作用是指定注解定义在方法上还是类上,或者都可以      接受一个数组,ElementType.TYPE表示定义在类,接口,枚举和注解上都可以
注意:TYPE是类,接口,枚举和注解的父类
@Target({ElementType.METHOD,ElementType.TYPE})
//自定义注解
public @interface ItcastAnnotation {}

@ItcastAnnotation
public class AnnotationTest
{
 public static void main(String[] args)
 {
  
  if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class))
  {
   ItcastAnnotation annotation = (ItcastAnnotation)      AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
   System.out.println(annotation);
  }
  
}

2.5.3)为注解增加高级属性
2.5.3.1)数组类型属性
int[] arrayAttr() default{1,2,3};
@MyAnnotation(arrayAttr={2,3,4})
如果数组属性中只有一个元素,这时候属性值部分可以省略大括号
2.5.3.2)枚举类型的属性
EnumTest.TrafficLamp lamp();
@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)
2.5.3.3)注解类型的属性
MetaAtation annotationAttr() default@MetaAnnotation("xxx");
@MyAnnotation(annotationAttr=@MetaAnnotation("yyy"))
可以认为上面这个@MyAnnotation是MyAnnotation类的一个实例对象,同样的道理可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下
MeAnnotation ma=myAnnotation.annotationAttr();
System.out.println(ma.value());

3 泛型Generic(这是jdk1.5的新特性)
3.1)如果没有定义泛型,集合是可以存进任何对象的,但是这样会造成安全隐患
/*
例子:没有定义泛型的安全隐患
*/
import java.util.ArrayList;
public class GenericTest {
 public static void main(String[]args)
 {
 ArrayList al=new ArrayList();
 al.add(1);
 al.add(2);
 al.add("abc");
 //这里把int类型的2强转为String类型,当然会包转换类型异常了
 String str=(String)al.get(1);
 System.out.println(str);
 }
}

引入泛型之后,把错误交给编译器去检查了,规定集合里的对象是什么类型,如果不是规定的类型,我就不让你编译通过
import java.util.ArrayList;
public class GenericTest {
 public static void main(String[]args)
 {
 ArrayList<Integer> al=new ArrayList<Integer>();
 al.add(1);
 al.add(2);
 //al.add("abc");
 //集合定义了泛型就不用进行强转了
 Integer str=al.get(1);
 System.out.println(str);
 }
}

3.2)ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:
整个ArrayList<E>称为泛型类型
ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型对象
ArrayList<Integer>中的<>念做typeof
ArrayList称为原始类型
3.2.1)参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报告警告,例如:
Collection<String> c=new Vector();
原始类型可以引用一个实际参数化类型的对象,编译报告警告,例如:
Collection c=new Vector<String>()
3.2.2)参数化类型不考虑类型参数的继承关系:
Vector<String> v=new Vector<Object>();//这是错误的
Vector<Object> v=new Vector<String>();//这也是错误的
3.2.3)在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句有错误:
Vector<Integer> vec=new Vector<Integer>[10];
下面的代码没有错:
Vector v1=new Vector<String>();
Vector<Object> v=v1;

3.3)自定义泛型的应用
GerericDao:dao data access objec-->crud就是增删改查
create:创建,增加
read:查,读
upudate:更新,修改
deleted:删除

4)类加载器及其委托机制的深入分析
4.1)java虚拟机中可以安装多个类加载器,系统默认三个注意类加载器,每个类负责加载特定位置的类BootStrap:JRE/lib/rt.jar
---ExtClassLoader:JRE/lib/ext/*.jar
------AppClasLoader:CLASSPATH指定的所有jar或目录

类加载器也是java类,因为类加载器把是java类的类都加载进来,显然必须有第一个类加载器不是java类,这正是BootStrap

java虚拟机中的所有类加载器采用具有父子关系的树形结构进行组织,在实例化每个类加载器对象时,
需要为其指定一个父级类装载器或者默认采用系统装载器为其父类加载

有一道面试题,能不能自己写一个类叫java.lang.System,为了不让我们写System类,类加载器采用委托机制这样能保证爸爸们优先查找
回答:通常不可以,但是我们要理解的是,类加载器采用委托机制,先交给父类加载器去执行找这个类,直到这个父类没有父类了,如果父类们没有找到,就依次的往下推,直到发起者,如果发起者这边也没有的话,就会报错,所以要我们写这个java.lang.System,我们要自己定义一个类加载器,避开委托机制

4.2)自定义加载器的编写原理分析
4.3)模版设计模式

4.4)类加载器的一个高级问题分析

5)代理
5.1)代理的概念与作用
程序中的代理:
要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理,日志,计算方法的运行时间,事务管理,等等,你准备如何做?
编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码.

5.2)AOP
交叉业务的编程问题即为面向方面的编程(Aspect oriented program,简称AOP),AOP的的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的.
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术.

5.3)动态代理技术
要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情!写成百上千个代理类,是不是太累了!
JVM可用在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类.
JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同相同接口的目标类的代理
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库.

例子:创建一个代理字节码文件对象package cn.home;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Collection;public class ProxyTest { public static void main(String[] args) throws SecurityException, NoSuchMethodException { /* Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);  //System.out.println(clazzProxy1.getName());  Constructor[] constructors = clazzProxy1.getConstructors();  for(Constructor constructor : constructors){   //System.out.println(constructor.getName());   Class[] clazzParameters = constructor.getParameterTypes();   StringBuilder sb = new StringBuilder();   sb.append("(");   for(Class clazzParameter : clazzParameters){    //System.out.println(clazzParameter.getName());    sb.append(clazzParameter.getName()+",");          }   if(clazzParameters != null && clazzParameters.length !=0)    sb.deleteCharAt(sb.length()-1);   sb.append(")");   System.out.println(sb.toString());  }*/    Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);  //System.out.println(clazzProxy1.getName());  Method[] methods = clazzProxy1.getMethods();  for(Method method : methods){   //System.out.println(constructor.getName());   Class[] clazzParameters = method.getParameterTypes();   StringBuilder sb = new StringBuilder();   sb.append("(");   for(Class clazzParameter : clazzParameters){    //System.out.println(clazzParameter.getName());    sb.append(clazzParameter.getName()+",");          }   if(clazzParameters != null && clazzParameters.length !=0)    sb.deleteCharAt(sb.length()-1);   sb.append(")");   System.out.println(sb.toString()); }}}


 

  

 

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

原创粉丝点击