`

张孝祥J2SE加强自学笔记(17-24)

    博客分类:
  • J2SE
阅读更多
17、透彻分析反射的基础类Class类:
Person p1 = new Person();
Class cls1 = java.util.Date.class //字节码1
Class cls2 = Person.class //字节码2
Class cls3 = p1.getClass()


当.java的源程序文件编译完成后,会编译成.class的字节码文件 当某个字节码文件要执行的时候首先会被load到内存
然后用这些字节码文件创建相应的对象。
面试题:Class.forName()的作用:
答:他的作用就是返回类的字节码,而返回的方式有两种,一种是这个类曾经加载过已经加载到JVM当中来了,那么可以直接得到 例如:p1.getClass()
或者Person.class就可以拿到字节码,另外一种方式是还没有加载过,要通过类加载器将它加载上来然后把它缓存起来例如:Class.forName(java.lang.String);
相同类型的类的字节码只有一份如:下面str1 = "abc"的例子就能说明这一点!!
代码举例:
public static void main(String[] args) throws Exception{
		String str1 = "abc";
		Class cls1 = str1.getClass();
		Class cls2 = String.class;
		Class cls3 = Class.forName("java.lang.String");
		//true
		System.out.println(cls1 == cls2);
		//true 得到的都是String类的字节码
		System.out.println(cls1 == cls3);
		
		//String.class是不是原始类型:false String 是一个类它不是原始类型
		System.out.println(cls1.isPrimitive());
		//Integer是int的包装类,所以false
		System.out.println(int.class == Integer.class);
		//Integer.TYPE返回的字节码指的是他所包装的那个类int的字节码,true
		System.out.println(int.class == Integer.TYPE);
		//整型数组他是数组类型他不是原始类型,所以最后一句是true,下面一句是false
		System.out.println(int[].class.isPrimitive());
		System.out.println(int[].class.isArray());

	}
总结:得到各个字节码对应的实例对象(Class类型)
(1)类名.class 例如:System.class
(2)对象.getClass() 例如:new Date().getClass()
(3)Class.forName("类名"),例如:Class.forName("java.lang.String");

九个预定义的Class实例对象:八种基本类型的.class + void.class void也是一种类型

18、理解反射的概念:的反射就是把Java类中的各个成分映射成相应的Java类

19、构造方法的反射应用:
代码举例:
//String.class拿到的那份字节码文件然后再得到他的一个参数为StringBuffer的那个构造方法
		Constructor construct = String.class.getConstructor(StringBuffer.class);
		//根据得到的这个构造方法,构造一个对象
		String abc = (String) construct.newInstance(new StringBuffer("abc"));
		System.out.println(abc);
		注意:反射的应用会导致程序的性能下降,因为他在内部处理的时候要缓存对象。

20、成员变量的反射:
举例代码:
//定义实体类
		public class ReflectionPoint {
			private int x;
			public int y;
	
			public ReflectionPoint(int x, int y) {
				super();
				this.x = x;
				this.y = y;
			}
		}
		//测试代码
		ReflectionPoint rp = new ReflectionPoint(3,5);
		//通过反射拿到RelectionPoint这个类的y成员变量
		Field pointY = rp.getClass().getField("y");
		//此时通过反射拿到的这个属性是属于整个类的,不属于某个对象,所以如果直接打印是打印不出具体的值的
		//如果想得到具体的值必须用get(Object obj)方法来说明取得的是那一个对象的值
		System.out.println(pointY.get(rp));
		
		//通过反射拿到RelectionPoint这个类的x成员变量
		//Field pointX = rp.getClass().getField("x");
		//如果用上面这句话来拿到x成员变量的话会出错,因为x是private的所以在外部是看不到这个方法的(NoSuchMethodExcepion),
		//所以用getDecleardField()方法
		//意为拿到类中声明过的变量,只要你在类中声明了不管是否是私有的,我都能拿到这个值
		Field pointX = rp.getClass().getDeclaredField("x");
		//设置x这个变量的访问权限为“可以访问”,虽然在上一句代码中我们已经拿到了x变量,但它是私有的还不能访问
		//所以在更改了他的访问权限之后才能够打印他的值。
		pointX.setAccessible(true);
		System.out.println(pointX.get(rp));

21、成员变量反射的综合案例: 将一个类中的String类型的成员变量的值中包含字符b的都替换成字符a
示例代码:
//定义实体类
			public class ReflectionPoint {
	
			private int x;
		
			public int y;
			
			public String str1 = "ball";
			
			public String str2 = "basketball";
			
			public String str3 = "itcast";
			
			public ReflectionPoint(int x, int y) {
				super();
				this.x = x;
				this.y = y;
			}
		
				@Override
				public String toString() {
			
				return "str1:" + str1 + "str2:" + str2 + "str3:" + str3; 
				}
		}
		//测试代码:
		public static void main(String[] args) {
			ReflectionPoint rp = new ReflectionPoint(3,5);
			changeStringValue(rp);
			System.out.println(rp);
		}
		
		private static void changeStringValue(ReflectionPoint rp) throws Exception {
			Field[] fields = rp.getClass().getFields();
			for(Field field : fields) {
				//此处比较的时候比较的是字节码:因为字节码只有一份所以用==比较合适,而不适合
				//用equals虽然也能够得出正确的结果
				if(field.getType() == String.class) {
					String oldValue = (String)field.get(rp);
					String newValue = oldValue.replace('b', 'a');
					field.set(rp, newValue);
				}
			}
		}

22、成员方法的反射:调用String类的charAt方法
示例代码:
String str1 = "abc";
		Method method = String.class.getMethod("charAt", int.class);
		System.out.println(method.invoke(str1, 1));
		//自动拆箱和装箱会将new Object[]{1}封装成一个Integer类型的对象
		System.out.println(method.invoke(str1, new Object[] {1}));

23、对接受数组参数的成员方法进行反射:
代码示例:
问题:通过反射的方式来调用TestArgments类的main方法时如何为invoke方法传递参数呢?按照jdk1.5的语法
整个数组是一个参数,当把一个字符串数组作为参数传递给invoke方法,javac会到底按照哪种语法进行处理呢
jdk1.5肯定要兼容jdk1.4的语法,会按照1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以在给main
方法传递参数的时候,不能使用代码main.invoke(null, new String[]{"xxx"}),javac只把他当做jdk1.4的语法进行
理解,而不把他当做jdk1.5的语法进行理解,因此会出现参数类型不对的问题。
解决办法:
(1)main.invoke(null, (Object)new String[]{"xxx"});
		(2)main.invoke(null, new Object[]{new String[]{"xxx"}));
		编译器会做特殊的处理,编译时不会把参数当做数组来看待,也就不会把数组打散成若干个参数了.
		
		
		public class ReflectionTest {
			public static void main(String[] args) throws Exception{
				String startingClassName = args[0];
				Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
				mainMethod.invoke(null, (Object)new String[]{"123", "222","33"});
				
			}

		class TestArguments{
			public static void main(String[] args){
				for(String arg : args){
					System.out.println(arg);
				}
			}
		}
24、数组与Object的关系及其反射类型:
示例代码:
int[] a1 = new int[]{1,2,3};
		int[] a2 = new int[5];
		int[][] a3 = new int[2][3]; 
		String[] a4 = new String[]{"a","b","c"};
		//true.因为同样都是数组类型且维数一样,他们的字节码肯定一样.
		System.out.println(a1.getClass() == a2.getClass());
		//false.虽然都是数组类型,但是数组的维数不一样,在1.5的编译器中甚至不能变异通过,说是
		//不兼容的操作数类型 
		System.out.println(a2.getClass() == a3.getClass());
		System.out.println(a1.getClass().getName());
		//false.数据的类型不一样,那么他们字节码的name当然不一样
		System.out.println(a1.getClass().getName() == a4.getClass().getName());
		
		Object aObj1 = a1;
		Object aObj2 = a4;
		Object[] aObje3 = a3;
		//Object[] aObje4 = a1;
		Object[] aObje5 = a4;
		
总结:
(1)具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
(2)代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class
(3)基本类型的一维数组可以被当做Object类型来使用,不能当做Object[]来使用,因为int
属于基本类型.非基本类型的一维数组既可以当做Object类型使用有可以当做Object[]来使用
(4)Arrays.asList()方法处理int[]和String[]时的差异:
//在jdk1.4中asList方法的定义:public static List asList(Object[] a);
//在jdk1.5中asList方法的定义:public static List<T> asList(T ... a);
//当我们传递a1的时候,因为a1是一个int[]不能转化为Object[],所以不能满足jdk1.4中方法参数的
//定义标准,转而交给jdk1.5所定义的方法来处理,在jdk1.5的定义中参数是一个可变的参数列表,会把
//a1看成是一个对象,所以转化为List之后打印出来就是[[I@de6ced],而传递a4的时候因为a4是String[],他符合jdk1.4方法
//中定义的参数类型Object[],因为jdk1.5要兼容1.4所以会首先按照jdk1.4所定义的方法来执行转换成List后
//打印结果为:[a, b, c]
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a4));//[a, b, c]
分享到:
评论

相关推荐

    张孝祥J2SE加强自学笔记(48-56)

    【张孝祥J2SE加强自学笔记(48-56)】主要涵盖了类加载器、代理类和动态类创建等Java核心知识点。 48、类加载器的问题实验分析: 在Java中,类加载器是负责查找并加载类的机制。在Web应用中,有多种类加载器,如...

    JAVA\张孝祥IT课堂-Java03-面向对象(上).ppt

    3. 多态(Polymorphism):多态是指同一个接口可以有不同的实现方式,即子类可以重写父类的方法,使得相同的操作可以作用于不同的对象,增强了代码的灵活性。Java中的方法重写(Override)和接口实现是多态的重要...

    张孝祥教授Javascript网页开发教程-02.pdf

    详细解释了html语言、css、javascript语法、dom对象编程、正则表达式,介绍了网页脚本编程的其他技术和知识。(由于上传限制,故将本教程分为6个部分上传,请全部下载后解压)

    张孝祥_高级j2se代码

    【张孝祥_高级j2se代码】这个资源包含了张孝祥老师精心编写的J2SE(Java 2 Standard Edition)高级代码示例,旨在帮助开发者深入理解和掌握Java核心技术。J2SE是Java平台的核心部分,它提供了丰富的类库和API,支持...

    张孝祥JAVA学习笔记

    张孝祥课程学习笔记,包括JAVA基础,JAVA高级,JavaScript全部的笔记,适合初学者。

    《张孝祥JAVA视频教程》完整版[RMVB]

    ed2k://|file|[张孝祥JAVA视频教程!(1-5课)].lesson01.[XiDong.Net].rmvb|555980477|1954514FA6C5757740064027D85826C1|h=EDKWEPSDDPS42DLGMONDGZPTQ7VF5BWX|/ ………………省略部分………… 第二部分 ed2k://|...

    张孝祥教授Javascript网页开发教程-01.pdf

    详细解释了html语言、css、javascript语法、dom对象编程、正则表达式,介绍了网页脚本不编程的其他技术和知识。(由于上传限制,故将本教程分为6个部分上传,请全部下载后解压)

    张孝祥教授Javascript网页开发教程-05.pdf

    详细解释了html语言、css、javascript语法、dom对象编程、正则表达式,介绍了网页脚本编程的其他技术和知识。(由于上传限制,故将本教程分为6个部分上传,请全部下载后解压)

    张孝祥Java邮件开发详解-高清扫描版-part1

    张孝祥Java邮件开发详解-高清扫描版-part1 绝对是精品 张孝祥的好书 。很大,分为2部分。

    j2se基础加强_张孝祥ppt

    j2se基础加强_张孝祥版ppt,对于java的基础提升是很有帮助的。

    张孝祥邮件开发ppt

    传智播客-------张孝祥老师--------------- javaMail开发PPT

    张孝祥java基础加强视频教程笔记

    【Java基础加强】张孝祥的Java教学视频涵盖了Java编程语言的基础到进阶知识,旨在帮助学习者巩固和提升Java编程技能。以下是根据教程笔记整理的一些关键知识点: 1. **Java简介**:Java是一种跨平台的面向对象的...

    张孝祥Java邮件开发详解-高清扫描版-part2

    张孝祥Java邮件开发详解-高清扫描版-part2

    张孝祥笔记

    jAVA基础+高新+7K知识点总结.chm 需要的可以下载

    Java基础加强--张孝祥版.ppt

    Java基础加强--张孝祥版 传智播客

    张孝祥Java多线程与并发库高级应用笔记

    ### 张孝祥Java多线程与并发库高级应用笔记概览 #### 一、Java多线程技术的重要性与挑战 Java线程技术是软件工程领域不可或缺的一部分,尤其在底层编程、Android应用开发以及游戏开发中,其重要性不言而喻。然而,...

    张孝祥老师讲课笔记

    ### 张孝祥老师讲课笔记:深入理解Windows程序运行机制 #### Windows程序设计与传统DOS方式的区别 张孝祥老师的讲课笔记强调了Windows程序设计与传统的DOS方式有着本质的不同,尤其体现在程序运行机制上。Windows...

    张孝祥交通灯管理系统笔记

    张孝祥交通灯管理系统笔记 面试题视频教程笔记

    笔记_张孝祥_Java多线程与并发库高级应用

    张孝祥Java多线程与并发库高级应用学习笔记,很经典的学习多线程和并发的资料。张孝祥Java多线程讲义笔记由张孝祥亲自整理,很实用的。

Global site tag (gtag.js) - Google Analytics