首页 > 编程语言 >Java-Day-34( Class 类特性 + Class 类常用方法 + Class 对象的获取方法 + 具有 Class 对象的类型 )

Java-Day-34( Class 类特性 + Class 类常用方法 + Class 对象的获取方法 + 具有 Class 对象的类型 )

时间:2023-07-20 16:12:39浏览次数:37  
标签:Java 对象 class System Day println Class out

Java-Day-34

Class 类特性

image-20230717112233407

  • Class 也是类,因此也继承 Object 类

  • Class 类对象不是 new 出来的,而是系统创建的

    • 通过类加载器 ClassLoader 类中的的 loadClass 方法
  • 对于某个类的 Class 类对象,在内存中只有一份

    • 不管是传统方法还是反射方法,一个类只会进一次 ClassLoad 类的 loadClass() 方法

      /*
       同是通过ClassLoad类加载 Dog 类的Class对象
       public Class<?> loadClass(String name) throws ClassNotFoundException {
       	 return loadClass(name, false);
       }
      */
      
      Class cls1 = Class.forName("com.hspJava.Dog");
      Class cls2 = Class.forName("com.hspJava.Dog");
      System.out.println(cls1.hashCode()); 
      System.out.println(cls2.hashCode());
      // hashCode值相同
      
  • 每个类的实例都会记得自己是由哪个 Class 实例所生成

  • 通过 Class 可以完整地得到一个类的完整结构,通过一系列 API

  • Class 对象是存放在堆的

    • 在 Class 类阶段 ( 加载阶段 )
  • 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据 ( 包括方法代码、变量名、方法名、访问权限等等 )

    • 在加载阶段还会生成一个方法区,内含一个该类的字节码二进制数据 ——> 引入到堆内 Class 类对象的这层关系,二进制数据转成 Class 类对象 ( 其实是种数据结构 ) 后操作更加容易

Class 类的常用方法

String className = "com.zyz.Dog";
Class cls = Class.forName(className);
System.out.println(cls); // 输出为类所在路径,即指明是哪个类的Class对象:class com.zyz.Dog
System.out.println(cls.getClass()); // 输出为运行类型:class java.lang.Class
//        得到包名
System.out.println(cls.getPackage().getName()); // com.zyz
//        得到全类名
System.out.println(cls.getName()); // com.zyz.Dog
//        通过cls创建对象实例
Dog dog = (Dog) cls.newInstance(); //
System.out.println(dog); // com.zyz.Dog@5ca881b5
//        通过反射获取属性
Field name = cls.getField("name");
System.out.println(name.get(dog)); // 土豆
//        通过反射给属性赋值
name.set(dog, "球球"); // 属性.set在(对象, 赋新值)
System.out.println(name.get(dog)); // 球球
//        得到所有的属性(字段)
Field[] fields = cls.getFields();
for (Field f: fields) {
    System.out.print(f.getName() + "~"); // name~age~
}

Class 对象的获取方法

Class.forName()

  • 在代码 / 编译阶段
  • 前提:已知一个类的全类名,且该类在路径下,可通过 Class 类的静态方法 forName() 获取,可能抛出 ClassNotFoundException
  • 应用场景:多用于配置文件,读取类全路径,加载类

类.class

  • Class 类 / 加载阶段 ( 堆中已有类对象 )
  • 前提:已知具体的类,该方式最为安全可靠,程序性能
  • 应用场景:多用于参数传递,比如通过反射得到对应构造器对象

对象.getClass

  • 就是之前一直用的获取运行类型的方法,就是在此运行阶段去找关联的在堆里的 Class 类对象,就是其在编译阶段真正加载进来的字节码文件的类,就是运行类型

  • 运行阶段 ( 对象已经有了 )

  • 前提:已知某个类的实例,调用该实例的 getClass() 方法获取 Class 对象

  • 应用场景:多用于有对象实例,即通过创建好的对象,获取 Class 对象

类加载器

  • 还可以通过类加载器得到 Class 对象

代码实例

//        1.Class.forName
String classAllPath = "com.zyz.Dog"; // 此处全路径应是通过读取配置文件获取
Class<?> cls1 = Class.forName(classAllPath);
System.out.println(cls1);

//        2.类名.class
Class cls2 = Dog.class;
System.out.println(cls2);

//        3.对象.getClass()
Dog dog = new Dog();
Class cls3 = dog.getClass();
System.out.println(cls3);

//        4.通过类加载器[四种]来获取到类的Class对象
//        (1)先得到类加载器dog
ClassLoader classLoader = dog.getClass().getClassLoader();
//        (2)通过来加载器得到Class对象
Class cls4 = classLoader.loadClass(classAllPath);
System.out.println(cls4);

// 		  上述输出全为 class com.zyz.Dog

//        cls1、2、3、4其实是同一个对象,输出全部相同
System.out.println(cls1.hashCode());
System.out.println(cls2.hashCode());
System.out.println(cls3.hashCode());
System.out.println(cls4.hashCode());

剩下两种比较特别的

  • 基本数据类型 ( int, char, boolean, float, double, byte, long, short ) 按如下方式得到 Class 类对象
Class cls = 基本数据类型.class;
  • 基本数据类型对应的包装类,可以通过 .TYPE 得到 Class 类对象
Class type = 包装类.TYPE;
  • 代码实例 ( 可知 int 与 Integer 实际上哈希值都是一样的,只是底层在自动装箱和拆箱 )
Class<Integer> integerClass = int.class;
Class<Character> characterClass = char.class;
//        看似为尖括号里的包装类,但输出可见还是最初的基本数据类型
System.out.println(integerClass); // int
System.out.println(characterClass); // char

Class<Integer> type = Integer.TYPE;
Class<Character> type1 = Character.TYPE;
System.out.println(type); // int
System.out.println(type1); // char

//        但int与Integer哈希值都是一样的,只是底层是自动装箱和拆箱
System.out.println(integerClass.hashCode());
System.out.println(type.hashCode());

具有 Class 对象的类型

  • 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
  • interface:接口 —— 可看作一种特殊的类
  • 数组
  • enum:枚举
  • annotation:注解
  • 基本数据类型
  • void
Class<String> cls1 = String.class; // 外部类
Class<Serializable> cls2 = Serializable.class; // 接口
Class<Integer[]> cls3 = Integer[].class; // 数组
Class<float[][]> cls4 = float[][].class; // 二维数组
Class<Deprecated> cls5 = Deprecated.class; // 注解
Class<Thread.State> cls6 = Thread.State.class; // 枚举(线程中的State就是枚举enum修饰的)
Class<Long> cls7 = long.class; // 基本数据类型
Class<Boolean> cls8 = Boolean.class; // 包装类
Class<Void> cls9 = void.class; // void
Class<Class> cls10 = Class.class; // Class本身也是有的

System.out.println(cls1); //class java.lang.String
System.out.println(cls2); //interface java.io.Serializable
System.out.println(cls3); //class [Ljava.lang.Integer;
System.out.println(cls4); //class [[F
System.out.println(cls5); //interface java.lang.Deprecated
System.out.println(cls6); //class java.lang.Thread$State
System.out.println(cls7); //long
System.out.println(cls8); //class java.lang.Boolean
System.out.println(cls9); //void
System.out.println(cls10); //class java.lang.Class

标签:Java,对象,class,System,Day,println,Class,out
From: https://www.cnblogs.com/zhu-ya-zhu/p/17568638.html

相关文章

  • java 固定长度编码
    Java固定长度编码在Java编程中,我们经常需要处理各种数据类型的编码和解码问题。其中,固定长度编码是一种常见的方式,它允许我们将不同长度的数据类型以固定的字节数进行表示。在本文中,我们将介绍Java中的固定长度编码的概念以及如何使用代码实现它。什么是固定长度编码?固定长度编......
  • java 获取当前线程id
    如何实现Java获取当前线程ID1.整体流程为了获取当前线程的ID,我们需要按照以下步骤进行操作:步骤描述1获取当前线程对象2从线程对象中获取线程ID下面我们将介绍如何逐步实现这些步骤。2.获取当前线程对象要获取当前线程的ID,我们首先需要获取当前线程对象......
  • java 根据距离展示内容
    Java根据距离展示内容实现步骤在Java中,如果我们想要根据距离展示内容,我们可以按照以下步骤进行操作:步骤描述1获取用户当前位置坐标2获取内容列表3计算用户与内容列表中每个内容的距离4根据距离排序内容列表5展示排序后的内容列表下面我会逐步解释......
  • java 获取当前外网
    Java获取当前外网在一些特定的场景中,我们可能需要获取当前运行Java程序所连接的外部网络的IP地址。这在一些网络应用程序中非常有用,例如分布式系统中的节点发现和通信。Java提供了一些方法来获取当前外网的IP地址。本文将介绍几种常见的方法,并提供相应的代码示例。使用HTTP请求......
  • java 父类构造子类
    Java父类构造子类在Java中,一个类可以继承另一个类,被继承的类称为父类或超类,继承的类称为子类或派生类。子类继承了父类的属性和方法,可以在此基础上添加新的属性和方法,或者修改父类的方法实现。当创建子类的对象时,子类的构造函数会首先调用父类的构造函数,以确保子类可以获得父类的......
  • java 获取当前unix时间戳
    Java获取当前Unix时间戳Unix时间戳是指从协调世界时(UTC)1970年1月1日00:00:00开始至今的总秒数。Unix时间戳被广泛用于计算机系统和编程语言中,用于表示时间和日期。在Java中,我们可以使用java.time包下的类来获取当前的Unix时间戳。使用java.time.Instant......
  • java 复制一行数据添加怎么做
    Java复制一行数据的方案在Java中,要复制一行数据,可以使用以下方案:方案一:使用数组复制可以使用System.arraycopy()方法将一个数组中的元素复制到另一个数组中,从而实现复制一行数据的目的。//原始数据int[]originalData={1,2,3,4,5};//复制数据int[]copiedData=ne......
  • java 获取抽象类的所有继承类
    Java获取抽象类的所有继承类在Java面向对象编程中,抽象类是通过abstract关键字定义的。抽象类不能被实例化,它只能被用作其他类的父类。抽象类中可以包含抽象方法和非抽象方法,而抽象方法必须在子类中实现。有时候我们需要获取一个抽象类的所有继承类,以便进行某些操作。本文将介绍......
  • java 复写map
    如何实现Java复写Map作为一名经验丰富的开发者,你要教会一位刚入行的小白如何实现Java中对Map的复写。这是一个重要的任务,因为Map是Java中常用的数据结构之一,掌握对其的复写能力对于开发者来说非常重要。下面将为你展示整个流程,并给出每一步的具体代码和注释。步骤一:创建一个新的......
  • java 获取10 100 1000
    Java中获取10、100、1000的方法在Java编程中,我们经常需要获取一定范围内的数字。本文将介绍几种获取10、100和1000的方法,并提供相应的代码示例。1.获取10方法一:直接使用数字获取数字10最简单的方法就是直接使用数字10。intnumber=10;System.out.println("获取的数字是:"+......