黑马程序员-高新技术(反射机制)



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

1、反射的概念

概念:简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

反射的引入:Object obj = new Student();

若程序运行时接收到外部传入的一个对象,该对象的编译类型是Object,但程序又需要调用该对象运行类型的方法:

1.若编译和运行类型都知道,使用 instanceof判断后,强转。

2.编译时根本无法预知该对象属于什么类,程序只能依靠运行时信息来发现对象的真实信息,这时就必须使用反射了。

3.要是想得到对象真正的类型,就得使用反射。


反射机制的优点与缺点为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,  

静态编译:在编译时确定类型,绑定对象,即通过。  

动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。  

一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

 

Class类:Java程序中的各个Java类属于同一类事物,描述这类事物的Java类就是Class类。

对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?

人 à Person

Java类 à Class

对比提问: Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class类代表Java类,它的各个实例对象又分别对应什么呢?

对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等;

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的;

用类来描述对象,类:描述数据的结构

用元数据来描述ClassMetaData(元数据):描述数据结构的结构

注意:一个类在虚拟机中只有一份字节码

  

2获得Class对象

如何得到各个字节码对应的实例对象?

每个类被加载后,系统会为该类生成对应的Class对象,通过Class对象可以访问到JVM中的这个类,

3种方式:

1调用某个类的class属性获取Class对象,如Date.class会返回Date类对应的Class对象(其实就是得到一个类的一份字节码文件)

2使用Class类的forName(String className)静态方法,className表示全限定名;如String的全限定名:java.lang.String;

3调用某个对象的getClass()方法。该方法属于Object类;Class<?> clz = new Date().getClass();

代码示例:

public class ClassDemo{
	public static void main(String[] args) throws Exception {
		//获得Class对象的方法(三种)
		//一:调用属性
		Class<String> c = String.class;
		System.out.println(c);//打印结果:class java.lang.String    				String.class就表示JVM中一份表示String类的字节码
		Class<String> c2 = String.class;
		System.out.println(c == c2);//true都是String类的字节码  		一个类在虚拟机中只有一份字节码;
		
		//二:使用forName()方法
		//Class cla = Class.forName("String");//ERROR,
		Class<String> cla = 															(Class<String>)Class.forName("java.lang.String");//必须用上全限定名,否则报错
		System.out.println(c == cla);//true
		
		//三:利用对象调用Object的getClass方法;
		Class c3 = new String().getClass();
		System.out.println(c == c3);//ture
	}
}

3九个预定义Class对象

 

基本的 Java 类型(booleanbytecharshortintlongfloat 和 double)和关键字 void通过class属性也表示为 Class 对象;

Class类中boolean isPrimitive() :判定指定的 Class 对象是否表示一个基本类型。

包装类和Void类的静态TYPE字段;Integer.TYPE == int.class ;   Integer.class == int.class; 

数组类型的Class实例对象:Class<String[]> clz = String[].class; 

数组的Class对象如何比较是否相等数组的维数和数组的类型;Class类中 boolean isArray() :判定此 Class 对象是否表示一个数组类型。

示例代码:

public class PreClassDemo{
	public static void main(String[] args) {		
		Class<?> in = int.class;
		System.out.println(in);//int
		Class<?> in2 = Integer.class;
		//包装类都有一个常量TYPE,用来表示其基本数据类型的字节码
		Class<?> in3 = Integer.TYPE;
		
		System.out.println(in2);//class java.lang.Integer
		System.out.println(in3);//int
		System.out.println(in3 == in);//true 包装类都有一个常量TYPE,用来表示其基本数据类型的字节码,所以这里会相等!
		System.out.println(in3 == in2);//false
		Class<String[]> s = String [].class;
		Class<int[]> i = int [].class;
		//System.out.println(i ==s);//编译根本就通过不了,一个是int,一个是String
	}
	//这两个自定义的方法是可以的,一个int,一个Integer//包装类与基本数据类型的字节码是不一样的
	public void show(int i){}
	public void show(Integer i){}
}

4、Class中得到构造方法Constructor方法Method、字段Field

 

常用方法:

Constructor类用于描述类中的构造方法:

Constructor<T> getConstructor(Class<?>... parameterTypes) 

返回该Class对象表示类的指定的public构造方法

Constructor<?>[] getConstructors()

返回该Class对象表示类的所有public构造方法

Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

返回该Class对象表示类的指定的构造方法,和访问权限无关;

Constructor<?>[] getDeclaredConstructors() 

返回该Class对象表示类的所有构造方法,和访问权限无关;

 

Method类用于描述类中的方法:

Method getMethod(String name, Class<?> ... parameterTypes) 

返回该Class对象表示类和其父类的指定的public方法

Method[] getMethods():  

返回该Class对象表示类和其父类的所有public方法

Method getDeclaredMethod(String name, Class<?>... parameterTypes) 

返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

Method[] getDeclaredMethods(): 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;


5、利用反射创建对象

 

创建对象两种方法:

1使用Class对象的newInstance()方法创建该Class对象的实例,此时该Class对象必须要有无参数的构造方法。

2使用Class对象获取指定的Constructor对象,再调用ConstructornewInstance()方法创建对象类的实例,此时可以选择使用某个构造方法。如果这个构造方法被私有化起来,那么必须先申请访问,将可以访问设置为true

方法1示例代码:

class User{
	/*private User(){//将默认的构造方法私有化的话就不可以再创建对象,两种方法都是这样
	}*/
	public String toString() {
		return "User对象创建成功!";
	}
}
public class NewInstanceDemo {
	public static void main(String[] args) throws Exception {
		//传统方式创建对象
		 System.out.println(new User());		 
		 //使用反射的方式
		 Class<User> c = User.class;
		 User u = c.newInstance();(直接newInstance的话必须保证默认的构造方法正常存在,也就是没有被私有化!这是前提条件)
		 System.out.println(u);
	}
}

方法2示例代码

import java.lang.reflect.Constructor;
class Per{
	private String name;
	private int age;
	private Per(){	
	}
	private Per(String name){
	}
	public String toString() {
		return "对象!!!";
	}
}
public class NewInstanceDemo{
	public static void main(String[] args) throws Exception {
		Class<Per> c = Per.class;
		//System.out.println(c.newInstance());;//证明利用无参的可以
		
		//先获得需要被调用的构造器(private 修饰的构造方法)
		Constructor<Per> con = c.getDeclaredConstructor();//调用默认的,什么都不要写
		System.out.println(con);//private junereflect624.Per()
		/*con = c.getDeclaredConstructor(String.class);获取指定的构造方法
		System.out.println(con);//private junereflect624.Per(java.lang.String)*/		
		//现在只需要执行这个构造器,
		/**
		 *  T newInstance(Object... initargs) 
		 		使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 
		 */
		
		//私有的成员是受保护的,不能直接访问
		//若要访问私有的成员,得先申请一下
		con.setAccessible(true);//允许访问
		Per p = con.newInstance();//成功,通过私有的受保护的构造方法创建了对象
		System.out.println("无参构造方法"+p);
		
		con = c.getDeclaredConstructor(String.class);
		System.out.println(con);//private junereflect624.Per(java.lang.String)
			
		con.setAccessible(true);//允许访问
		p = con.newInstance("heima");//成功,通过私有的受保护的构造方法创建了对象
		System.out.println("String构造方法"+p);
	}
}



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

黑马训练营:http://edu.csdn.net/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值