黑马程序员_基础加强二

来源:互联网 发布:信阳毛尖 知乎 编辑:程序博客网 时间:2024/05/16 08:27

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

 

反射

1.反射就是把java类中的各种成分映射成相应的Java类。

2.反射的基石(classjava程序中的各个java类属于同一类事物,描述这类事物的java类名就是class

3.反射的好处:大大增强了程序的扩展性。弊端:必须先明确类,在创建类的对象。

4.得到字节码对应的实例对象。

       (1)类名.class

(2)对象.getClass()

(3)Class.forName("类名")

5.Class.forName("java.lang.String")

Class.forName的作用:返回字节码。

返回方式有两种:(1)这个字节码曾经被加载过,已存在于Java虚拟机中直接返回。

(2)Java虚拟机中还没有字节码,则用内加载器去加载把加载进来的字节码放在虚拟机中,以后要得到这份字节码就不用加载了。

6.只要是在源程序中出现的类型,都有各自的Class实例对象。

原始类型:System.out.println(int.class.isPrimitive());

数组类型System.out.println(int[].class.isArray());

Constructor

1.代表某个类中的构造方法。

       (1)得到某个了的所有构造方法

              Constructor[]constructors = class.forName("java.lang.String").getConstructors();

(2)得到某一个构造方法

Constructor constructor1 =String.class.getConstructor(StringBuffer.class);

(3)创建实例对象

       通常方式:String str = new String (new StringBuffer("abc"));

             反射方式:String str2 = (String)constructor1.newInstance(newStringBuffer("abc"));

2.Class.newInstance()方法:该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。

Field

1.代表某个类中的一个成员变量

2. getField();对所有公有变量获得字段

getDeclaredField();对所有私有变量获得字段

示例:

ReflectPoint pt1= new ReflectPoint(3,5);

       FieldfieldY = pt1.getClass().getField("y");

       //fieldY的值是多少?是5,错!fieldY不是对象上的变量,而是类上,要用它去取某个对象对应的值。

       System.out.println(fieldY.get(pt1));

       FieldfieldX = pt1.getClass().getDeclaredField("x");

       fieldX.setAccessible(true);//将此对象的accessible标志设置为指示的布尔值。暴力反射

       System.out.println(fieldX.get(pt1));   

Method

1.代表某个类中的成员方法。

2.调用方法:

       通常方式:System.out.println(str.charAt(1));

       反射方式:System.out.println(charAt.invoke(str,1));

示例:

MethodmethodCharAt = String.class.getMethod("charAt", int.class);//得到类中的方法

System.out.println(methodCharAt.invoke(str1,1));

System.out.println(methodCharAt.invoke(str1,new Object[]{2}));

3.JDK1.4JDK1.5invoke方法的区别:

       JDK1.5:publicobject invoke(Object obj,Object…args)

       JDK1.6:publicobject invoke(Object obj,Object[] args)

即按JDK1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码也可以用JDK1.4改写为charAt.invoke("str", newObject[]{1}))形式。

用反射方式执行某个类中的main方法

1.main方法的参数是一个字符串,如果用反射的方法来调用main方法时,如何为invoke方法传递参数。

2.解决办法:

Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);

//mainMethod.invoke(null, new Object[]{newString[]{"111","222","333"}});//第一种方法

mainMethod.invoke(null, (Object)newString[]{"111","222","333"});//第二种方法

编译器会做特殊的处理,编译时不把参数当作数组看待,也就不会把数组打散成若干个参数了。

数组的反射

1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的calss的实例对象。

2.基本类型的一维数组可以被当作Object类型使用,不能当作object[]类型使用。

3.非基本类型的一维数组,既可以当作object类型使用,又可以当作object[]类型使用。

示例:

int [] a1 = newint[]{1,2,3};

       String[] a4 = new String[]{"a","b","c"};

PrintObject(a1);

PrintObject(a4);

PrintObject("xyz");

private staticvoid PrintObject(Object obj) {

Class clazz = obj.getClass();

       if (clazz.isArray()) {

              int len = Array.getLength(obj);

                     for(int i = 0; i < len; i++) {

                            System.out.println(Array.get(obj,i));  

                     }    

              }else{

                     System.out.println(obj);

              }

       }

反射的作用

1.实现框架的功能。

2.框架类与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

3.因为在写程序时无法知道要被调用的类名,所以在程序中无法直接new某个类的实例对象了,而要用反射方式来做。

示例:

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

       InputStreamips = ReflectTest2.class.getResourceAsStream("resource/config.properties");

       //用类加载器配置文件

       Propertiesprops = new Properties();

       props.load(ips);

       ips.close();

       StringclassName = props.getProperty("className");

       Collectioncollections = (Collection)Class.forName(className).newInstance();

       ReflectPointpt1 = new ReflectPoint(3,3);

       ReflectPointpt2 = new ReflectPoint(5,5);

       ReflectPointpt3 = new ReflectPoint(3,3);

       collections.add(pt1);

       collections.add(pt2);

       collections.add(pt3);

       collections.add(pt1);

       System.out.println(collections.size());

}//打印2

 

内省JavaBean

1.JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

2.JavaBean的属性是根据其中的settergetter方法来确定的,而不是根据其中的成员变量。总之:一个类被当作JavaBean使用时,JavaBean的属性是根据方法名推断出来的,他根本看不到java类内部的成员变量。

private static void setProperties(Pointpt1, String Name,Object value) throws Exception {

              PropertyDescriptorpd2  = newPropertyDescriptor(PropertyName, pt1.getClass());

              MethodmethodSetX = pd2.getWriteMethod();

              methodSetX.invoke(pt1,value);

              System.out.println(pt1.getX());

       }

private static ObjectgetProperty(ReflectPoint pt1, String PropertyName)throws Exception {

              PropertyDescriptorpd  = newPropertyDescriptor(PropertyName, pt1.getClass());

              Method methodGetX= pd.getReadMethod();

              ObjectretVal = methodGetX.invoke(pt1);

       return retVal;

}

BenUtils工具包

1.BeanUtils类先get原来设置好的属性,再将其set为一个新值。get属性时返回的结果为字符串,set属性时可以接受任意类型的对象,通常使用字符串。

2.PropertyUtil类先get原来设置好的属性,再将其set为一个新值。get属性时返回的结果为该属性本来的类型,set属性时只接受该属性本来的类型。

3.jar包拷贝到工作间的一个文件下,右击Build Path,选择Add to Build Path

类加载器

1.加载类的工具。

2.作用:在Java程序中用到一个类,出现了这个类的名字,那么Java虚拟机首先把类的字节码加载到内存里面来,通常字节码文件的原始信息放在硬盘上classpath指定目录下,把.class文件的内容加载到硬盘里面来,在对其进行处理,处理完的结果就是字节码,就把class文件从硬盘上加载进来,对其进行处理。

3.系统默认三个主要类加载器:BootStrapJRE/lib/rt.jar),ExtClassLoaderJRE/lib/ext/*.jar),AppClassloader(Classpath指定所有jar或目录)

4.类加载器的委托机制:每个类加载器加载类时,优先委托给其上级类加载器,当所有根类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛出classNotFoundException

5.自定义的类加载器必须继承classLoaderloadclass方法与findClass方法,defineClass方法。

示例

编写对class文件进行加密的工具类

public class MyClassLoader extendsClassLoader {

       publicstatic void main(String[] args)throws Exception {//加密部分

              StringsrcPath = args[0];

              StringdestDir = args[1];

              FileInputStreamfis = new FileInputStream(srcPath);

              StringdestFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);

              StringdestPath = destDir +"\\"+destFileName;   

              FileOutputStreamfos = new FileOutputStream(destPath);

              cypher(fis,fos);

              fis.close();

              fos.close();           

       }    

       privatestatic void cypher(InputStream ips,OutputStream ops)throws Exception{

              intb = -1;

              while((b= ips.read()) !=-1){

                     ops.write(b^0xff);

              }    

       }

       privateString classDir;  

       @Override//解密部分

   protected Class<?> findClass(String name) throwsClassNotFoundException {

    String  calssFileName =classDir+"\\"+name.substring(name.lastIndexOf('.')+1)+".class";

              try{

                     FileInputStreamfis = new FileInputStream(calssFileName);

                     ByteArrayOutputStreambos = new ByteArrayOutputStream();

                     cypher(fis,bos);

                     fis.close();

                     byte[]bytes = bos.toByteArray();

                     returndefineClass(bytes,0,bytes.length);

              }catch(Exceptione){

                     e.printStackTrace();

              }

           return super.findClass(name);

    }

       publicMyClassLoader(String classDir){

              this.classDir= classDir;

       }

}

//调用类加载器

public class ClassLoaderTest {

       publicstatic void main(String[] args) throws Exception {

              System.out.println(

                            ClassLoaderTest.class.getClassLoader().getClass().getName()

                            );

              System.out.println(System.class.getClassLoader());

              ClassLoaderloader = ClassLoaderTest.class.getClassLoader();

              while(loader !=null){

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

                     loader= loader.getParent();

              }

              System.out.println(loader);

              Classclazz =

 newMyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAttachment");

              Dated1 = (Date)clazz.newInstance();

              System.out.println(d1);

       }

}

//进行加密处理,加密处理后存入itcastlib文件夹下

public class ClassLoaderAttachment extendsDate {

       publicString toString(){

              return"hello,itcast";

       }

}

代理

1.代理就是为已存在的多个接口的目标类中的方法添加一些系统功能。

2.交叉业务:把安全,事务,日志等功能贯穿到好多个模块中。

3.重要原则:不要把供货商暴露给客户。

4.jvm创建动态类及其实例对象,需要给他提供哪些信息?

三个方面:

(1)生成的类中有哪些方法,通过让其实现哪些接口的方式进行告知;

       (2)产生的类字节码必须有一个关联的类加载器对象;

        (3)生成的类中的方法的代码是怎样的,也得由我们提供,把我们的代码卸载一个约定好了的接口。对象的方法中,把对象传给他,他调用我的方法,即相当于插入了我的代码。提供执行代码的对象就是那个InvocationHander对象,他是在创建动态类的实例对象的构造方法时传递进去的了。在上面的InvocationHander对象的invoke方法中加一点代码,就可以看到这些代码别调用运行了。

5.Proxy.newInstance方法直接一步就创建出代理对象。

Object obj =clazzProxy1.newInstance();

示例:创建动态的实例对象,用反射获得构造方法,编写一个最简单的InvocationHander类。

Class clazzProxy1 =Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

System.out.println(clazzProxy1.getName());

Constructor[]constructors = clazzProxy1.getConstructors();

for(Constructorconstructor : constructors){

       Stringname = constructor.getName();

       StringBuildersBuilder = new StringBuilder(name);

       sBuilder.append('(');

       Class[]clazzParams = constructor.getParameterTypes();

       for(ClassclazzParam:clazzParams){

              sBuilder.append(clazzParam.getName()).append(',');

       }

       if(clazzParams!=null&& clazzParams.length != 0)

       sBuilder.deleteCharAt(sBuilder.length()-1);

       sBuilder.append(')');

       System.out.println(sBuilder.toString());

       }

动态生成的类的内部代码

       Method[]methods = clazzProxy1.getMethods();

       for(Methodmethod : methods){

              String name = method.getName();

              StringBuildersBuilder = new StringBuilder(name);

              sBuilder.append('(');

              Class[]clazzParams = method.getParameterTypes();

              for(ClassclazzParam:clazzParams){

                     sBuilder.append(clazzParam.getName()).append(',');

              }

              if(clazzParams!=null&& clazzParams.length != 0)

              sBuilder.deleteCharAt(sBuilder.length()-1);

              sBuilder.append(')');

              System.out.println(sBuilder.toString());

       } 

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

 

0 0