Class

Class类

下面通过Class.forName来获取一个实例对象

  1. /**
  2. * 反射Demo
  3. *
  4. * @author: Fcant
  5. */
  6. public class ReflectionDemo {
  7. public static void main(String[] args) throws ClassNotFoundException {
  8. // 通过反射获取类的Class对象
  9. Class c1 = Class.forName("com.moxi.interview.study.annotation.User");
  10. Class c2 = Class.forName("com.moxi.interview.study.annotation.User");
  11. Class c3 = Class.forName("com.moxi.interview.study.annotation.User");
  12. System.out.println(c1.hashCode());
  13. System.out.println(c2.hashCode());
  14. System.out.println(c3.hashCode());
  15. }
  16. }
  17. /**
  18. * 实体类:pojo,entity
  19. */
  20. class User {
  21. private String name;
  22. private int id;
  23. private int age;
  24. public User() {
  25. }
  26. public String getName() {
  27. return name;
  28. }
  29. public void setName(String name) {
  30. this.name = name;
  31. }
  32. public int getId() {
  33. return id;
  34. }
  35. public void setId(int id) {
  36. this.id = id;
  37. }
  38. public int getAge() {
  39. return age;
  40. }
  41. public void setAge(int age) {
  42. this.age = age;
  43. }
  44. @Override
  45. public String toString() {
  46. return "User{" +
  47. "name='" + name + '\'' +
  48. ", id=" + id +
  49. ", age=" + age +
  50. '}';
  51. }
  52. }

上面通过反射获取了三个对象,输出对应对象的hashcode码,会发现

  1. 1173230247
  2. 1173230247
  3. 1173230247

它们的hashcode码是一样的,这就说明了:

  • 一个类在内存中只有一个Class对象
  • 一个类被加载后,类的整体结构都会被封装在Class对象中

在Object类中定义了以下的方法,此方法将被所有子类继承

  1. public final Class getClass()

以上方法的返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。
image.png
也就是说,通过对象来获取到它的Class,相当于逆过程
通过对照镜子可以得到的信息:某个类的属性,方法和构造器,某个类到底实现了那些接口。对于每个类而言,JRE都为其保留一个不变的Class类型对象,一个CLass对象包含了特定某个结构的有关信息

  • Class本身也是一个类
  • Class对象只能由系统建立对象
  • 一个加载的类在JVM中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个Class实例所生成
  • 通过Class可以完整地得到一个类中所有被加载的结构
  • Class类是Reflection的根源,针对任何想动态加载、运行的类、唯有先获得相应的Class对象

    Class类常用的方法

  • ClassforName(String name):返回指定类name的Class对象

  • newInstance():调用缺省构造函数,返回Class对象的一个实例
  • getName():返回此Class对象所表示的实体(类,接口,数组或void)的名称
  • getSuperClass():返回当前Class对象的父类Class对象
  • getinterfaces():返回当前对象的接口
  • getClassLoader():返回该类的类加载器
  • getConstructors():返回一个包含某些Constructor对象的数组
  • getMethod(String name, Class… T):返回一个Method对象,此对象的形参类型为paramsType
  • getDeclaredFields():返回Field对象的一个数组

    获取对象实例的方法

  • 若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高

  • Class clazz = Person.class;
  • 已知某个类的实例,调用该实例的getClass()方法获取Class对象
  • Class clazz = person.getClass()
  • 已经一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取,HIA可能抛出ClassNotFoundException
  • Class clazz = Class.forName(“demo01.Sutdent”)
  • 内置数据类型可以直接通过 类名.Type
  • 还可以利用ClassLoader

    1. /**
    2. * Class类创建的方式
    3. *
    4. * @author: Fcant
    5. */
    6. class Person {
    7. public String name;
    8. public Person() {
    9. }
    10. public Person(String name) {
    11. this.name = name;
    12. }
    13. @Override
    14. public String toString() {
    15. return "Person{" +
    16. "name='" + name + '\'' +
    17. '}';
    18. }
    19. }
    20. class Student extends Person{
    21. public Student() {
    22. this.name = "学生";
    23. }
    24. }
    25. class Teacher extends Person {
    26. public Teacher() {
    27. this.name = "老师";
    28. }
    29. }
    30. public class ClassCreateDemo {
    31. public static void main(String[] args) throws ClassNotFoundException {
    32. Person person = new Student();
    33. System.out.println("这个人是:" + person.name);
    34. // 方式1:通过对象获得
    35. Class c1 = person.getClass();
    36. System.out.println("c1:" + c1.hashCode());
    37. //方式2:通过forName获得
    38. Class c2 = Class.forName("com.moxi.interview.study.annotation.Student");
    39. System.out.println("c2:" + c2.hashCode());
    40. // 方式3:通过类名获取(最为高效)
    41. Class c3 = Student.class;
    42. System.out.println("c3:" + c3.hashCode());
    43. // 方式4:基本内置类型的包装类,都有一个Type属性
    44. Class c4 = Integer.TYPE;
    45. System.out.println(c4.getName());
    46. // 方式5:获取父类类型
    47. Class c5 = c1.getSuperclass();
    48. }
    49. }

    哪些类型可以有Class对象

    class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
    interface:接口
    []:数组
    enum:枚举
    annotation:注解@interface
    primitive type:基本数据类型
    void

    1. /**
    2. * 获取Class的方式
    3. *
    4. * @author: 轻狂书生FS
    5. */
    6. public class GetClassDemo {
    7. public static void main(String[] args) {
    8. Class c1 = Object.class; // 类
    9. Class c2 = Comparable.class; // 接口
    10. Class c3 = String[].class; // 数组
    11. Class c4 = int[][].class; // 二维数组
    12. Class c5 = Override.class; // 注解
    13. Class c6 = ElementType.class; // 枚举
    14. Class c7 = Integer.class; // 基本数据类型
    15. Class c8 = void.class; // void,空数据类型
    16. Class c9 = Class.class; // Class
    17. System.out.println(c1);
    18. System.out.println(c2);
    19. System.out.println(c3);
    20. System.out.println(c4);
    21. System.out.println(c5);
    22. System.out.println(c6);
    23. System.out.println(c7);
    24. System.out.println(c8);
    25. System.out.println(c9);
    26. }
    27. }

    最后运行结果为:

    1. class java.lang.Object
    2. interface java.lang.Comparable
    3. class [Ljava.lang.String;
    4. class [[I
    5. interface java.lang.Override
    6. class java.lang.annotation.ElementType
    7. class java.lang.Integer
    8. void
    9. class java.lang.Class

    同时需要注意,只要类型和维度一样,那就是同一个Class对象

    1. int [] a = new int[10];
    2. int [] b = new int[10];
    3. System.out.println(a.getClass().hashCode());
    4. System.out.println(b.getClass().hashCode());

    这两个的hashcode是一样的

    Java内存分析

    java内存分为以下三部分


  • 存放new的对象和数组
  • 可以被所有的线程共享,不会存放别的对象引用

  • 存放基本变量(会包含这个基本类型的具体数值)
  • 引用对象的变量(会存放这个引用在对堆里面的具体地址)
  • 方法区
  • 可以被所有线程共享
  • 包含了所有的class和static变量