黑马程序员--进阶篇:反射,内省

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

1.java的反射:java程序中的各个java类属于同一个类事物,描述这类事物的java类名就是class。


2.class ci01 = Date.class //"Date.class"表示Data类的字节码


3.一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的
   类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象
   来表示。


4.如何得到各个字节码对应的实力对象(class类型)
1.类名.class, 例如:System.class;
2.对象.getClass(), 例如:new Date().getClass(); //得到创建对象的字节码
3.class.forname("类名"),例如:class.forname("java.util.Date"); //反射时


5.反射(Reflect)示例代码:
package zhang;
/**
 * 对于java中的反射进行实验
 * 1.获取字节码
 * @author THINK
 *
 */
public class Reflect {
public static void main(String[] args) throws ClassNotFoundException{
String str = "abc";

Class cl01 = str.getClass(); //将字符串对象"str"d得到它的class字节码

Class cl02 = String.class; //

Class cl03 = Class.forName("java.lang.String");

System.out.println(cl01 == cl02);
System.out.println(cl01 == cl03);

System.out.println();  //判断是否是原始类型
}
}




6.九个预定义class实例对象:
1.class.isPrimitive方法作用:判定指定的class对象是否表示一个基本类型。
2.String不是一个基本数据类型,它是一个类。


7.示例代码:
System.out.println(cl01.isPrimitive());  //判断是否是原始类型
System.out.println(int.class.isPrimitive());
System.out.println(String.class.isPrimitive());


8.九个定义Class实例对象:
1.Int.class == Integer.TYPE;


9.反射(Reflect):反射就是把java类中的各种成分映射成相应的java类。
1.首先要先的到字节码;
2.


10.一个类中的组成部分:成员变量,方法,构造方法,包;


11.Constructor(构造函数)类:
1.Constructor类代表某个类中的一个构造方法;
2。代码示例:
//28.29行必须使用“StringBuffer”这个,来获取字节码
Constructor constructor = String.class.getConstructor(StringBuffer.class); //这样可以有一个"Constructor"的构造方法
String st1 = (String)constructor.newInstance(new StringBuffer("abc")); //必须使用“String”这个,将其转换成String类型的

System.out.println(st1.charAt(2)); //"charAt"是求出某个字节上某位字节


12.创建示例对象:
1.通常方式:String str =  new String(new StringBuffer("abc"));
2.反射方式:String str  = (String)constructor.newInstance(new StringBuffer("abc"));


13.关于Class.newInstance()方法:
1.例子:String obj = (String)Class.forName("java.lang.String").newInstance();
2.该方法内部先得到默认的构造方法,然后用该构造方法创建示例对象。
3.该方法内部的具体代码写时,用到了缓存机制来保存默认构造方法的实例对象。


14.创建一个类的实例对象的步骤:class -->constractor -->new object


15.反射会导致程序性能下降;


16.为什么要使用反射:因为程序是支持第三方的插件的,而开发的时候并不知道,所以无法在代码中
    new出来,但是反射是可以的,通过反射,动态加载程序集,然后读出来,检查
    标记之后再实例对象,就可以获得正确的类实例。


17.Field(字段)类:代表某个类中的一个成员变量。


18.生成构造方法的源代码:Source -->generate Constractor using field(生成field类的构造方法);


19.将String数据中一些数据进行修改(示例代码):
package zhang;
import java.lang.reflect.*;
public class Reflect_01 {
public static void main(String[] args) throws Exception{

Constructor constructor = String.class.getConstructor(StringBuffer.class);
String st = (String)constructor.newInstance(new StringBuffer("abc"));

//使用ReflectPoint的反射
ReflectPoint reflectPoint = new ReflectPoint(0, 0); //给变量传递一个值
// Field fieldy = reflectPoint.getClass().getField("y"); //"y"是ReflectPoint的一个变量,但是“y”是一个公共变量
//
// System.out.println("y值:" + fieldy.get(reflectPoint)); //获取字节码的数值
//
// Field fieldx = reflectPoint.getClass().getField("x"); //注意:此处“x”为私有变量
// fieldx.setAccessible(true); //"accessible(可取的)",用于强制访问私有变量的数据
// System.out.println("x的值:" + fieldx.get(reflectPoint));


//对对象内的数据进行修改
changvalueof(reflectPoint);
System.out.println(reflectPoint);

}
public static void changvalueof(Object object) throws Exception{
Field[] fields = object.getClass().getFields();

for(Field field : fields){ //for循环的加强
if(field.getType() == String.class){
String oldvalue = (String)field.get(object);
String newvalue = oldvalue.replace("s", "z"); //”replace(取代)”的作用进行数值的替换;
field.set(object, newvalue); //将对象的数值进行替换
}
}
}
}


package zhang;


public class ReflectPoint {

private int x = 3 ;
public int y = 4 ;

public String z = "ejvdsacds";
public String p = "dfsfakd";
public String k = "dfdkjdz";

//生成 x, y的构造方法
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}

/**
* 使用toString方法对对象进行重载
*/
public String toString(){
return z + ":" + p + ":" + k + ":";

}


}






20.什么时候要使用toString:因为当print检测到输出的是一个对象而不是字符或者数字时,那么它会
   调用这个对象类里面的toString方法,而且toString方法一般会被用
   来重载,也就是说,如果让这个方法实现特定的输出,所以会去重载它


21.Method类:代表某个类中的一个成员方法


22.得到method类中的某一个方法:
1.Method charc = Class.forName("java.lang.String").getMethod("charc",int class);


23.Method类的调用方法:
1.通常方法:System.out.println(str.charc(1));
2.反射方法:System.out.println(charc.invoke(str, 1));



24.invoke(调用);


25.代码示例:
package zhang;
import java.lang.reflect.*;
public class Reflect02 {
public static void main(String[] args) throws Exception{
String string = "abc";
//使用并测试Method
Method method = String.class.getMethod("charAt", int.class); //"charAt"是表示方法名,而且这是在在此处必须使用,"int.class"表示重载的类型
System.out.println(method.invoke(string, 0)); //获取在某个位置的字节码
System.out.println(method.invoke(string, new Object[]{0})); //获取字节码的另一钟方法,按照jdk1.4的方法进行调用;
}
}


26.用反射方式去执行某个类中的main方法:
1.mainMethod.invoke(null, new Object[]{new String[]{"..."}});
2.mainMethod.invoke(null,(Object)new String[]{"..."});


27.数组的反射:
1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
(1).示例代码:
package zhang;


public class Reflect_arr {
public static void main(String[] args){

int[] arr1 = new int[1];
int[] arr2 = new int[2];

int[][] arr3 = new int[1][2];
String[] arr4 = new String[1];

//进行比较
System.out.println(arr1.getClass() == arr2.getClass());
System.out.println(arr1.getClass() == arr3.getClass());
System.out.println(arr1.getClass() == arr4.getClass());

}
}


2.代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。


29.Arrays.asList()方法处理int[]和String[]时的差异;


30.基本类型的一位数组可以被当作Object类型使用,不能当作Object[]类型使用,非基本类型的一维
数组,既可以当作Object类型使用,又可以当作Object[]类型使用


31.Array工具类用于完成对数组的反射操作;


32.Collect(采集)中ArrayList与HashSet的区别,示例代码:
package zhang;


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;


/**
 * 用于比较使用ArrayList与的区别
 * @author THINK
 *
 */
public class reflect03 {
public static void main(String[] args){

//使用ArrayList
Collection collection = new ArrayList();
ReflectPoint reflectPoin1 = new ReflectPoint(3, 5);
ReflectPoint reflectPoin2 = new ReflectPoint(4, 5);
ReflectPoint reflectPoin3 = new ReflectPoint(3, 5);

collection.add(reflectPoin1);
collection.add(reflectPoin2);
collection.add(reflectPoin1);

System.out.println(collection.size()); //输出使用ArrayList集合大小



//使用Hashset
Collection collections = new HashSet();
ReflectPoint reflection3 = new ReflectPoint(5, 6);
ReflectPoint reflection4 = new ReflectPoint(4, 6);
ReflectPoint reflection5 = new ReflectPoint(5, 6);

collections.add(reflection3);
collections.add(reflection4);
collections.add(reflection3);

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

}
}


33.关于hashset与hashcode的区别:
1。通常来说,一个类的两个示例对象用equals()方法比较的结果相等时,它们的哈希码必须
相等,但反之则不成立,即equals方法比较结果不相等的对象可以有相同的哈希码,
或者说哈希码相同的两个对象的equals方法比较的结果可以不等,例如:字符串“BB”
和“Aa”的equals方法比较结果肯定不相等,但它们的hashCode方法返回值却相等


2.当一个对象被存储进HashSet的集合中后,就不能修改这个对象中的那些参与计算哈希值的
字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中是的哈希值就 不同了,在
这种情况下,即使在contains方法是用该对象的单前引用作为的参数区HashSet集合中检索对
象,也将返回着不懂啊对象的结果,这也会导致无法从hashSet集合中单独删除当前对象,从
而造成内存泄漏


34.Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每
个键及其对应值都是一个字符串。 


35.因为在写程序是无法知道要被调用的类名,所以i,在程序中无法直接使用new某个类的实力对象了,
而是哟啊用反射方式来做。


36.getRealPath():一定要用完整的路径,但完整的路径不是硬编码,而是运算出来的;


37.getResourceAsStream():用于查找具有给定名称的资源。


//InputStream inputStream = new FileInputStream("file.properties"); //第一种资源加载器

//InputStream inputstream = reflect03.class.getClassLoader().getResourceAsStream("zhang\file.properties"); //第二种方法
InputStream inputstream = reflect03.class.getResourceAsStream("zhang\file.properties");
Properties properties = new Properties(); //Properties 可保存在流中或从流中加载
properties.load(inputstream);
inputstream.close();

String className = properties.getProperty("className");
Collection collection1 = (Collection)Class.forName(className).newInstance();

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


38.内省(introspector) --》了解javaBean:
1.javaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问
  私有字段,且方法名符合某种命名规则。
2.如果要在模块之间传递多个信息,可以将这些信息装到一个javaBean中,这种javaBean的实例
 对象通常称之为值对象(Value Object),简称VO,这些信息在类中用私有变量


39.javaBean的是特殊的java类;


40.PropertyDescriptor(属性描述符);


41.示例代码:
40.javaBean属性的书写方法:去掉get或set后,剩下的名称是javaBean的属性名,使用时把首字母改成
小写,即: getAge -->Age -->如果第二字母是小写,则首字母小写-->age


41.当一个类被当作javaBean使用时,javaBean的属性是根据方法名推断出来的,它根本看不到java类
内部的成员变量。


42.一个符合javaBean特点的类可以当作普通类一样进行使用,但把它当javaBean用肯定需要带来一些
额外的好处。优点:
1.在javaEE的开发中,经常要使用到javaBean,很多环境就要求按照javaBean
 方式进行操作
2.JDK中提供了对javaBean进行操作的一些API,这套API就称为内省,如果要
 你自己区通过getX的方法来访问私有的X时,用内省的的API操作javaBean
  比用普通类的方式更方便。


43.Beanutils工具包:get属性时返回的结果为字符串,set属性时可以接受任意类型的对象,通常使用
字符串,


44.java注解:“@SuppressWarnings("")”,向编译器提示知道调用的是过时的方法,不用提示。


44.注释,注解(annotation);


45.“@Override”复制父类的注解;


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


47.注解的总结:注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于
没有某种标记,以后,javac编译器,开发工具和其它程序可以用反射来了解你的类及各种元素
上有无何种标记,,标记可以加在包,类,字段,方法,方法的参数以及局部变量上。


48.根据发射测试题的问题,引用@Retention元注解,其三中取值:RetentionPolicy.SOURCE、
RetentionPolity.CLASS、RetentionPolity.RUNTIME;分别对应:java源文件—》class文件——》内存中的字节码


49.“@Override”的属性:用于javac,在源代码时有用,即@RentionPolicy.SOURCE阶段


50.“SuppressWamings”的属性:因为在编译器阶段,所以不再那三个阶段;


51."@Deprecated"的属性,是在编译器阶段,


52.设置缺省属性(示例代码):
package zhang;
@Annotation(color = "red")
public class AnnotationTest {


//这里写一个请勿提示的注解
//@SuppressWarnings("deprecation")

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


if(AnnotationTest.class.isAnnotationPresent(Annotation.class)){
Annotation annotation = (Annotation)AnnotationTest.class.getAnnotation(Annotation.class);
System.out.println(annotation.color());
}


package zhang;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;


@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation {
String color() default "blue"; //设置缺省值,即当为给对象设置数值时,则会有默认的数值
String value();
}


53.数组类型,枚举类型,注解类型的属性(示例代码):
package zhang;
@Annotation(color = "red",value = "abc", arr = { 0 }) //注释的方法出现的对象,则此处必须使用
public class AnnotationTest {


//这里写一个请勿提示的注解
//@SuppressWarnings("deprecation")

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


if(AnnotationTest.class.isAnnotationPresent(Annotation.class)){
Annotation annotation = (Annotation)AnnotationTest.class.getAnnotation(Annotation.class);
System.out.println(annotation.color());
System.out.println(annotation.value());
System.out.println(annotation.arr().length);
System.out.println(annotation.lamp().nextColor().name());
System.out.println(annotation.mete().value());
}



}


package zhang;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;


@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation {
String color() default "blue"; //设置缺省值,即当为给对象设置数值时,则会有默认的数值
String value();
int[] arr();
Enum.Color lamp() default Enum.Color.Red;
MeteAnnoation mete() default @MeteAnnoation("asf"); //缺省默认值
}


package zhang;


public @interface MeteAnnoation {
String value();
}




54.java中注解规范,查看java的language specification


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值