Java classes and class loading mechanism

Focuses on the following aspects (Class class understanding, understanding of Java's class loading mechanism, learn to use the ClassLoader class loads carried)

1. Understand the Class class

For each class, JRE retains a constant type Class object for. A Class object contains information about a specific class.

  Class objects can only be established by the target system

     A class in the JVM will be only one instance of Class

    Each instance of the class will remember which is generated by the Class instance

    1:  What Class that?

      Class is a class :( / lowercase class representation is a class type, uppercase Class represents the name of the class )
public class ReflectionTest {
    @Test
    public void testClass() { Class clazz = null; } } //Class的定义 public final class Class<T> implements java.io.Serializable, java.lang.reflect.GenericDeclaration, java.lang.reflect.Type, java.lang.reflect.AnnotatedElement {....}

2: Class This class encapsulates what information?

  Class is a class that encapsulates information about the current object corresponding to class
  1, a class has attributes, methods, and other configurations, for example, a Person class, an Order class, a class Book, these different classes are , now we need a class used to describe the class, which is class, it should have a class name, property, method, structure or the like. Class class is used to describe the class

  2, Class class is a result of a mirror of the object, the object can see what their properties, method, constructor, interface, etc. which implements

      3. For each category concerned, JRE retains a constant type Class object for. A Class object contains information about a specific class.
    4.Class object can only be established by the system objects, a class (not an object) in the JVM will be only one instance of Class

 

package reflect;

public class Person {
    String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person() {
        super();
        
    }
    
    
}
It defines a Person type

 

Get a class object class by Class

 

public  class ReflectionTest { 
    @Test 
    public  void testClass () { 
       Class clazz = null ; 
       
       // 1. Class object obtained 
       clazz = the Person. class ; 
       
       System.out.println ();   // insert breakpoints 
    } 
}

 

At a breakpoint, you can see on the image information contained in Class

 

 

 Similarly, the values ​​of these attributes can be acquired

public class ReflectionTest {
    @Test
    public void testClass() {
       Class clazz = null;
       
       //1.得到Class对象
       clazz = Person.class;
       //2.返回字段的数组
       Field[] fields = clazz.getDeclaredFields();
       
       System.out.println();  //插入断点
    }
}

查看fields的内容

 

 

 对象为什么需要照镜子呢?

    1. 有可能这个对象是别人传过来的

    2. 有可能没有对象,只有一个全类名 

  通过反射,可以得到这个类里面的信息

获取Class对象的三种方式

  1.通过类名获取      类名.class    

  2.通过对象获取      对象名.getClass()

  3.通过全类名获取    Class.forName(全类名)

 

 

public class ReflectionTest {
  @Test
  public  void testClass() throws ClassNotFoundException{
      Class clazz=null;
      //1、通过类名获取对象    类名.class
      clazz=Person.class;
      Field[] filed=clazz.getDeclaredFields();
      Field[] fields=clazz.getFields();
      System.out.println(Arrays.deepToString(filed));
      System.out.println(Arrays.deepToString(fields));
      //2、通过对象名
      //这种方式是用在传进来一个对象,却不知道对象的类型时候用
      Person person=new Person();
      clazz=person.getClass();
      Object obj=new Person();
      clazz=obj.getClass();
      //3、通过全类名(会抛出异常)
      String  classname="reflect.Person";
      clazz=Class.forName(classname);
      
      //字符串的例子
      clazz=String.class;
      clazz="javaTest".getClass();
      clazz=Class.forName("java.lang.String");
      System.out.println();
      
  }

Class类的常用方法

 

方法名

功能说明

static Class forName(String name)

返回指定类名 name 的 Class 对象

Object newInstance()

调用缺省构造函数,返回该Class对象的一个实例

Object newInstance(Object []args)

调用当前格式构造函数,返回该Class对象的一个实例

getName()

返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

Class getSuperClass()

返回当前Class对象的父类的Class对象

Class [] getInterfaces()

获取当前Class对象的接口

ClassLoader getClassLoader()

返回该类的类加载器

Class getSuperclass()

返回表示此Class所表示的实体的超类的Class

 

 Class类的newInstance()方法

@Test
  public void testNewInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
      //1、获取Class对象
      String className="reflect.Person";
      Class clazz=Class.forName(className);
      //利用class对象的newInstance方法创建一个类的实例
      Object obj=clazz.newInstance();
      System.out.println(obj);
  }

     可以看出确实是创建了一个Person实例
  但是Person类有两个构造方法,到底是调用的哪一个构造方法呢

  实际调用的是类的无参数的构造器。所以在我们在定义一个类的时候,定义一个有参数的构造器,作用是对属性进行初始化,还要写一个无参数的构造器,作用就是反射时候用。

  一般地、一个类若声明一个带参的构造器,同时要声明一个无参数的构造器

 

2.ClassLoader

类装载器是用来把类(class)装载进 JVM 的。JVM 规范定义了两种类型的类装载器:启动类装载器(bootstrap)和用户自定义装载器(user-defined class loader)。 JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示

 

 

 

 @Test
  public void testClassLoader() throws ClassNotFoundException{
      //1、获取一个系统的类加载器(可以获取,当前这个类ReflecTest就是它加载的)
    ClassLoader classLoader=ClassLoader.getSystemClassLoader();
    System.out.println(classLoader);
     //2、获取系统加载器的父类加载器(扩展器加载器,可以获取)
    classLoader=classLoader.getParent();
    System.out.println(classLoader);
    //3、获取扩展类加载器的父类加载器(引导加载器,不可以获取)
    classLoader=classLoader.getParent();
    System.out.println(classLoader);
    //4、测试当前类用哪个类加载器进行加载(系统类加载器)
    classLoader=Class.forName("reflect.ReflectionTest").getClassLoader();
    System.out.println(classLoader);
   //5、测试JDK提供的Object类由哪个类加载器负责加载(引导类)
    classLoader=Class.forName("java.lang.Object").getClassLoader();
    System.out.println(classLoader);
}

使用类加载器获取当前类目录下的文件

 

 

 首先,系统类加载器可以加载当前项目src目录下面的所有类,如果文件也放在src下面,也可以用类加载器来加载

调用 getResourceAsStream 获取类路径下的文件对应的输入流.

 

 

 @Test
  public void testClassLoader() throws ClassNotFoundException{
     /* //1、获取一个系统的类加载器(可以获取,当前这个类ReflecTest就是它加载的)
    ClassLoader classLoader=ClassLoader.getSystemClassLoader();
    System.out.println(classLoader);
     //2、获取系统加载器的父类加载器(扩展器加载器,可以获取)
    classLoader=classLoader.getParent();
    System.out.println(classLoader);
    //3、获取扩展类加载器的父类加载器(引导加载器,不可以获取)
    classLoader=classLoader.getParent();
    System.out.println(classLoader);
    //4、测试当前类用哪个类加载器进行加载(系统类加载器)
    classLoader=Class.forName("reflect.ReflectionTest").getClassLoader();
    System.out.println(classLoader);
   //5、测试JDK提供的Object类由哪个类加载器负责加载(引导类)
    classLoader=Class.forName("java.lang.Object").getClassLoader();
    System.out.println(classLoader);*/
    
   //src目录下直接加载
    InputStream in1=null;
    in1=this.getClass().getResourceAsStream("text1.txt");
    //放在内部文件夹,要写全路径
    InputStream in2=this.getClass().getResourceAsStream("reflect/text2.txt");
    }

参考:https://www.cnblogs.com/zhaozw/p/10857841.html

Guess you like

Origin www.cnblogs.com/zouhong/p/12103548.html