理解java中反射,区别Class.forName(),Class.forName().instance() ,new,如果获取对象中的方法和字段「建议收藏」

理解java中反射,区别Class.forName(),Class.forName().instance() ,new,如果获取对象中的方法和字段「建议收藏」理解java中反射,区别Class.forName(),Class.forName().instance() ,new,如果获取对象中的方法和字段

大家好,又见面了,我是你们的朋友全栈君。

先了解一些基本的概念:运行时,编译时,编译型,解释型,类加载器,动态加载类 
什么是编译?将原程序翻译成计算机语言,就是二进制代码,在java中是将.java文件也就是源程序翻译成.class的字节码 
什么是编译时?将原程序翻译成计算机语言的过程中,将.java翻译为.class文件的过程 
什么是运行时?就是在启动这个程序的时候,在java中是,类加载器加载.class文件,并交给jvm处理 
什么是编译型语言?将原程序一次性全部转换为二进制代码,然后执行程序 
什么是解释型语言?转换一句,执行一句,java是既编译又解释的语言 
编译型语言和解释型语言的区别:编译型语言效率高,依赖于编译器,但是跨平台差,解释型的效率低,依赖于解释器,但跨平台强 
什么是类加载器?类加载器就是JVM中的类装载器,作用就是将编译好的.class字节码运到检查器进行安全检查的,检查通过后开始解释执行 
什么是运行时动态加载类? 
反射就是可以将一个程序(类)在运行的时候获得该程序(类)的信息的机制,也就是获得在编译期不可能获得的类的信息,因为这些信息是保存在Class对象中的,而这个Class对象是在程序运行时动态加载的 
它 就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成对象。类在运行的时候,可以得到该类的信息,并且 可以动态的修改这些信息。class对象是在运行的时候产生的,通过class对象操作类的信息是在运行时进行的,当运行 程序的时候,类加载器会加载真正需要的类,什么是真正需要的呢?就是该类真正起作用,如:有该类的对象实例,或该类调用了静态方法属性等 

那么如何实现反射呢?

要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产 生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。 三种方式得到Class对象: 

1.调用对象的getClass方法,返回该对象的Class对象。

2.Class.forName(“类的完整名字”);可以在类不确定的情况下实例化Class,最灵活。

3.Class c=类名.class 

举例说明吧:

package test;
/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class A {
	
	private String name="ees";
	
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public A (){
		System.out.println("默认构造方法执行了");
	}
	
	static{
		System.out.println("执行静态代码块");
	}
	
	{System.out.println("执行非静态代码块");}
	

}

测试类:

package test;
/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class Test {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
		A a=new A();
		System.out.println(a.getClass());
		System.out.println(Class.forName("test.A"));
		System.out.println(A.class);
	}
}

上面依次是三种得到class对象对象的方式:

执行结果:

执行静态代码块
执行非静态代码块
默认构造方法执行了
class test.A
class test.A
class test.A

这里要注意是先执行非静态代码块,再执行默认构造方法。

—————————————————————————————————————————————————–

下面我们回过头看class.forName()方法,这个方法提供了两个重载方法

先看第一个:

package test;
/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class Test {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
//		A a=new A();
//		System.out.println(a.getClass());
//		System.out.println(Class.forName("test.A"));
//		System.out.println(A.class);
		
//		Class c=Class.forName("test.A");
		
		
		Class c=Class.forName("test.A",false,A.class.getClassLoader());
	}
}

true:是否实例化该类,也就是说实际上调用Class.forName(“类的完整名字”)加载类时执行初始化

this.getClass().getClassLoader()调用类加载器

上面forName第二个参数是false,因此,不会实例化,因此上面没有任何出入结果,这个例子证实了先执行类加载器,再执行静态方法块。

把false改成true,就会有输出结果:

执行静态代码块

再看第二个forname重载方法:

package test;
/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class Test {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
//		A a=new A();
//		System.out.println(a.getClass());
//		System.out.println(Class.forName("test.A"));
//		System.out.println(A.class);
		
//		Class c=Class.forName("test.A",true,A.class.getClassLoader());
		
		Class c=Class.forName("test.A");
	}
}

这个结果就跟上面一样了,

执行静态代码块

可是上面的实例化的对象是个class,并没有准确到一个确切对象,那么怎么使用forName来创建呢?

package test;
/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class Test {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
//		A a=new A();
//		System.out.println(a.getClass());
//		System.out.println(Class.forName("test.A"));
//		System.out.println(A.class);
		
//		Class c=Class.forName("test.A",true,A.class.getClassLoader());
		
//		Class c=Class.forName("test.A");
		A a= (A) Class.forName("test.A").newInstance();
		System.out.println(a.getName());
	}
}

结果:

执行静态代码块
执行非静态代码块
默认构造方法执行了
ees

需要补充的是:Class.forName(“完整类名”).newInstance();的用法相当于直接new();

—————————————————————————————————————————————————————————–

这里证实一个类再类加载中只加载一次:

package test;
/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class Test {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
		A a1=new A();
		A a2=new A();
//		System.out.println(a.getClass());
//		System.out.println(Class.forName("test.A"));
//		System.out.println(A.class);
		
//		Class c=Class.forName("test.A",true,A.class.getClassLoader());
		
//		Class c=Class.forName("test.A");
		A a= (A) Class.forName("test.A").newInstance();
		
		System.out.println(a.getName());
	}
}

结果:

执行静态代码块
执行非静态代码块
默认构造方法执行了
执行非静态代码块
默认构造方法执行了
执行非静态代码块
默认构造方法执行了
ees

这里相当于new了3次 ,但是只执行了一次静态代码块。

 

——————————————————————————————————————————————————————————

下面通过反射获取类中的方法、字段等属性:

package test;

import java.lang.reflect.Method;

import org.apache.tools.ant.types.CommandlineJava.SysProperties;

/**
 * 
 * @author liuxin
 * @date   2018年8月22日
 */
public class Test {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
//		A a1=new A();
//		System.out.println(a.getClass());
//		System.out.println(Class.forName("test.A"));
//		System.out.println(A.class);
//		Class c=Class.forName("test.A");
//		A a= (A) Class.forName("test.A").newInstance();
		
		
		Class c=Class.forName("test.A",true,A.class.getClassLoader());
		Method[] methods=c.getMethods();
		for(Method m:methods){
			System.out.println(m);
		}
	}
}

结果:

执行静态代码块
public java.lang.String test.A.getName()
public void test.A.setName(java.lang.String)
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

同理,还有获取所有字段的方法:

Field[] fields=c.getDeclaredFields();
		for(Field f:fields){
			System.out.println(f);
		}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/106036.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • groupby函数详解

    groupby函数详解pandas中groupby函数用法详解1groupby()核心用法2groupby()语法格式3groupby()参数说明4groupby()典型范例1groupby()核心用法(1)根据DataFrame本身的某一列或多列内容进行分组聚合,(a)若按某一列聚合,则新DataFrame将根据某一列的内容分为不同的维度进行拆解,同时将同一维度的再进行聚合,(b)若按某多列聚合,则新D…

    2022年5月9日
    89
  • npm下载和使用(超详细)

    npm下载和使用(超详细)NPM(NodePackageManager)简称为Node包管理工具安装(首先我们需要安装Node)Mac如果没有安装Node可以使用mac的包管理神器HomeBrew进行安装,首先下载HomeBrew,接下来在终端执行以下命令brewinstallnode也可以选择去官网下载pkg安装包,记得下载长期稳定版,即LTS版windows可以在官网中选择windows相对应的版本,同样下载稳定版本,一步点击安装即可使用当下载好Node后我们就可以使用n..

    2025年7月10日
    0
  • delphi7中idHTTP的使用

    delphi7中idHTTP的使用1.直接idhttp:Tidhttp声明一个var变量是不能使用的。必须有控件2.使用IdHTTP调post接口,xml格式IdHTTP1.HandleRedirects:=True;//允许头转向IdHTTP1.ReadTimeout:=30000;//请求超时设置IdHTTP1.HTTPOptions:=IdHTTP1.HTT…

    2022年7月15日
    55
  • uC/OS-II中,各个任务间可以共享任务堆栈_什么是多任务系统

    uC/OS-II中,各个任务间可以共享任务堆栈_什么是多任务系统想让uC/OS-Ⅱ管理用户的任务,用户必须要先建立任务。用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务:OSTaskCreate()或OSTaskCreateExt()。OSTaskCreate()与uC/OS是向下兼容的,OSTaskCreateExt()是OSTaskCreate()的扩展版本,提供了一些附加的功能。用两个函数中的任何一个都可以建立任务。  任务可以在多任…

    2022年9月5日
    2
  • django配置文件详解_django实时读取日志

    django配置文件详解_django实时读取日志前言django框架的日志通过python内置的logging模块实现的,既可以记录自定义的一些信息描述,也可以记录系统运行中的一些对象数据,还可以记录包括堆栈跟踪、错误代码之类的详细信息。log

    2022年7月31日
    6
  • 用JavaScript对GridView进行上移下移,保存排序

    用JavaScript对GridView进行上移下移,保存排序

    2021年7月27日
    54

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号