zoukankan      html  css  js  c++  java
  • 黑马程序员-类加载机制和反射。

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

    • Class的由来(用于表述字节码文件的类的名称就是Class)

    当程序主动使用一个类时。如果该类还未加载到内存当中。则系统会通过加载,链接,初始化3个步骤来对类进行初始化,如果没有意外,JVM将会联系完成这个步骤。

    而类的加载就是将类的class文件读入内存当中,并为此创建一个java.lang.Class对象,那么我们可以理解,我们在程序当中使用任何一个类时,系统都会为此创建一个java.lang.Class对象。 

    可以理解的就是:我们如果获取到字节码对象,就可以操作字节码对象当中的内容,这样我们不久可以动态的获取类中的内容并且使用了。

     摘录:我们知道。类是一类对象的抽象,那么我们可以这样想一下,类也是一种对象,而类是一种概念层次的东西,我们说描述主要用于定义和描述其他事物,但是概念本身也需要一些描述,也就是说需要另外一个类来描述这些类的抽象,那么我们的Class类就产生了。

    • JAVA程序中的类属于同一个事物,描述这类事物的类就叫Class

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

    但是我们可以总结出,这些对象也会有相同的类型,这个类型就是Class类

    • 基本的 Java 类型(booleanbytecharshortintlongfloatdouble)和关键字 void 也表示为 Class 对象。
    • Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
    • 那么我们如何获得类的Class对象呢?(就是如何获取字节码对象)可以理解这是反射的核心。

    我们用一段代码来演示

    		//获取到字节码的3种方法
    		String str = "zhulang";
    		
    		/*
    		 * 方式一
    		 * 使用Object类当中的getClass方法。
    		 * 但是这个方法必须要创建未知类对象,在调用getClass方法
    		 */
    		Class class1 = str.getClass();
    		
    		/**
    		 * 方式二
    		 * 使用该类的静态class属性获取。这个方式和一一样,还是要知道未知的类。
    		 */
    		Class class2 = String.class;
    		
    		/**
    		 * 方式三。
    		 * 通过Class类当中的静态方法 forName(String className)来完成。
    		 * 该方法根基传入类的名称,自动去classPath路径下去寻找改名称相同的类文件
    		 * 然后通过类加载器进行加载,并且在内存当中生成类的字节码文件对象。
    		 */
    		Class class3 = Class.forName("java.lang.String");
    		
    		System.out.println(class1 == class2);
    		System.out.println(class1 == class3);
    

      

    结果是

     


    反射

    反射:就是把java类中个成份映射一个Java类,包括Class,Method,Field,Constructorh和Array等等,这些类分别代表类,方法,Field,构造器和数组。

    反射的由来

    1.在不明确日后出现什么样的实现类是,可以扩展出去,对外提供配置文件,让后期的实现类都定义在配置文件中,

    2.该程序会读取配置文件并根据指定的名字寻找对应的类。

    3.找到对应的类进行对象的建立,

    4.并且调用该类对象的成员,

    可以说反射大大提高程序的扩展性。


    • 反射字段
    private void fieldDemo() throws Exception
    	{
    		/*
    		 * 获取获取指定类当中的指定名称的字段
    		 * 思路:先要获取到该类的字节码文件对象
    		 * 2.通过字节码文件对象 获取当中的成员字段
    		 * 	
    		 */	
    		String className ="com.text.Person";
    		
    		//获取到 该类的字节码文件对象
    		Class perClass = Class.forName(className);
    		//获取到成员字段的对象
    		Field field = perClass.getDeclaredField("age");
    		//获取到,那么我们要进行字段的设置一个值,要想设置值,那么我们得实列化一个成员对象。
    		Object obj = perClass.newInstance();
    		field.setAccessible(true);
    		//对象也创建了,那么我们怎么给字段设置值呢?
    		field.set(obj, 18);	
    		//我们现在来获取方法来设置字段的值	
    		//我们来操作方法了。
    		System.out.println(field.get(obj));
    
    	}
    • 反射构造函数演示
      /**
      	 * 反射构造函数
      	 */
          private static void  constructorDemo() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException 
      	{
      		//反射构造函数有什么作用。有构造函数我们就能够对构造函数进行初始化
          	
          	String className = "com.text.Person";
          	
          	//获得Class对象   我的理解是理解是里面包含 类里面成员映射的许多对象
          	Class percls = Class.forName(className);
          	
          	//获取Person类的构造函数的对象
          	Constructor con = percls.getConstructor(String.class);
          	Person obj  =(Person) con.newInstance("zhulang");
          	System.out.println(obj.getName());
          	
      	 
    • 反射方法
       /**
           * 反射方法。
           */
          private static void MethodDemo() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException 
      	{
      		//获取到Class集合
          	Class metClass = Class.forName("com.text.Person");
          	
          	//那么我们要获取到方法类。 
          	Method met= metClass.getMethod("show", null);
          	
          	//获取指定的对象
          	Object obj = metClass.newInstance();
          	//通过该该对象调用该方法。
          	met.invoke(obj,null);
          	
          	/*
          	 * 上面两行代码等同于
          	 * Person per = new Person();
          	 * per.show();
          	 */
      	}
      

        

    • 上面用到的类Person
    public class Person
    {
    	private String name;
    	private int age ; 
    	public Person()
    	{
    		
    	}
    	
    	public  Person(String str)
    	{
    		this.name =str;
    		
    	}
    	public String getName()
    	{
    		return name;
    	}
    	public void setName(String name)
    	{
    		this.name = name;
    	}
    	public void show()
    	{
    		System.out.println("Person Show run");
    	}
    }
    

      

        

     

  • 相关阅读:
    【原创】xenomai内核解析---内核对象注册表—xnregistry(重要组件)
    【原创】xenomai内核解析--双核系统调用(三)--如何为xenomai添加一个系统调用
    【原创】xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务
    【原创】xenomai内核解析--信号signal(二)---xenomai信号处理机制
    环境篇:数据同步工具DataX
    环境篇:DolphinScheduler-1.3.1安装部署及使用技巧
    大数据篇:一文读懂@数据仓库(PPT文字版)
    如何把百万级别的订单根据金额排序
    数据库系统设计概述
    《Redis设计与实现》笔记4—独立功能的实现
  • 原文地址:https://www.cnblogs.com/ganwei/p/4574624.html
Copyright © 2011-2022 走看看