zoukankan      html  css  js  c++  java
  • JAVA中类、实例与Class对象

    已同步更新至个人blog:http://dxjia.cn/2015/08/java-class-object/

          类是面向对象编程语言的一个重要概念,它是对一项事物的抽象概括,可以包含该事物的一些属性定义,以及操作属性的方法。面向对象编程中,我们都是以类来编码。

    实例

    简单理解,就是new,就是对类的实例化,创建这个类对应的实际对象,类只是对事物的描述,而实例化就相当于为这个描述新开辟了一块内存,可以改变这块区域里的各种属性(成员变量),当然,也可以实例化多块区域,只是不同的对象而已。

    Class

    注意这里C大写了,与类概念区分开,在java里,Class是一个实实在在的类,在包 java.lang 下,有这样一个Class.java文件,它跟我们自己定义的类一样,是一个实实在在的类,Class对象就是这个Class类的实例了。在Java里,所有的类的根源都是Object类,而Class也不例外,它是继承自Object的一个特殊的类,它内部可以记录类的成员、接口等信息,也就是在Java里,Class是一个用来表示类的类。(o(∩_∩)o 有点绕啊,抓住关键一点,Class是一个实实在在的类,可以为它创建实例,也就是本文后面提到的Class对象,也看叫做Class实例)。

      java提供了下面几种获取到类的Class对象的方法:

        1) 利用对象实例调用getClass()方法获取该对象的Class实例;
            2) 使用Class类的静态方法forName("包名+类名"),用类的名字获取一个Class实例

            3)运用 类名.class 的方式来获取Class实例;

      我们知道java世界是运行在JVM之上的,我们编写的类代码,在经过编译器编译之后,会为每个类生成对应的.class文件,这个就是JVM可以加载执行的字节码。运行时期间,当我们需要实例化任何一个类时,JVM会首先尝试看看在内存中是否有这个类,如果有,那么会直接创建类实例;如果没有,那么就会根据类名去加载这个类,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便会为这个类产生一个Class对象(一个Class类的实例),用来表达这个类,该类的所有实例都共同拥有着这个Class对象,而且是唯一的。

     

    总结

      在java里,类只是信息描述的,写明了有哪些内部属性及接口,你可以理解为是定义了一套规则;而Class对象在java里被用来对类的情况进行表述的一个实例,也就是是类的实际表征,可以理解为是对规则的图表化,这样JVM才能直观的看懂,可以看做是一个模版;而类的实例化对象,就是通过模版,开辟出的一块内存进行实际的使用。

    例子:

    我们通过一个例子来理解Class实例,为了说明方便,我们新建一个包名深点的类。

    新建Name.java(当然,该文件要放在comdxjiasample的目录下)

     1 package com.dxjia.sample;
     2 
     3 public class Name {
     4     static int count = 0;
     5     static {
     6         count++;
     7         System.out.println("Name Class Loaded! count = [" + count + "]" );
     8     }
     9 
    10     public Name() {
    11         System.out.println("Name Constructor called!");
    12     }
    13 
    14 }

    再在根目录新建一个Test主类

     1 import com.dxjia.sample.Name;
     2 
     3 public class Test {
     4     static {
     5         Name mName;
     6         System.out.println("Test Class loaded");
     7     }
     8     
     9     public  static void main(String[] args) {
    10         System.out.println("entern Test main()");
    11         
    12         // Name.class
    13         Class mClassPointClass;
    14         // Class.forName("完整包名+类名")
    15         Class mClassForName;
    16         // new 对象后,对象.getClass()
    17         Class mClassObjectPointClass1;
    18         Class mClassObjectPointClass2;
    19 
    20         try {
    21             //测试 类名.class
    22             mClassPointClass = Name.class;
    23             System.out.println("mClassPointClass = " + mClassPointClass);
    24             
    25             //测试Class.forName()
    26             mClassForName = Class.forName("com.dxjia.sample.Name");
    27             System.out.println("mClassForName = " + mClassForName);
    28 
    29             //测试Object.getClass()
    30             Name name1 = new Name();
    31             mClassObjectPointClass1 = name1.getClass();
    32             System.out.println("mClassObjectPointClass1 = " + mClassObjectPointClass1);
    33         } catch (ClassNotFoundException e) {
    34             // TODO Auto-generated catch block 
    35             e.printStackTrace();
    36             return;
    37         } 
    38 
    39         Name name2;
    40         System.out.println("defined one Name object");
    41         name2 = new Name();
    42         System.out.println("Name object instance done!");
    43         
    44         mClassObjectPointClass2 = name2.getClass();
    45         
    46         if (mClassForName == mClassPointClass
    47             && mClassPointClass == mClassObjectPointClass1
    48             && mClassObjectPointClass1 == mClassObjectPointClass2) {
    49             System.out.println("all the Class object equal...");
    50         }
    51     }
    52 }

    分别对他们进行编译:

    1 javac comdxjiasampleName.java
    2 javac Test.java

    执行:

    1 java Test

    代码中使用了static静态代码块来进行实验,一个类的运行,JVM做会以下几件事情 1、类装载 2、链接 3、初始化 4、实例化;而初始化阶段做的事情是初始化静态变量和执行静态方法等的工作,而且永远只执行一次。

    输出结果:

    Test Class loaded
    entern Test main()
    mClassPointClass = class com.dxjia.sample.Name
    Name Class Loaded! count = [1]
    mClassForName = class com.dxjia.sample.Name
    Name Constructor called!
    mClassObjectPointClass1 = class com.dxjia.sample.Name
    defined one Name object
    Name Constructor called!
    Name object instance done!
    all the Class object equal...

    通过结果可以看出在使用 类名.class获得Class实例时,并不会触发类的初始化,而 Class.forName方法就会触发,当然实例化对象肯定也是会触发的,但因为static代码块只执行一次,所以不会再有打印,最后的打印,说明一个类的Class实例只有唯一的一个。

    扩展:

    对于Class.forName("")方法,可以看看下面这篇文章,结合起来理解,会更清晰:理解Class.forName()

     

  • 相关阅读:
    Splay模板(bzoj 1588)
    PDD----配对堆
    [BZOJ4025] 二分图 LCT/(线段树分治+并查集)
    FFT模板 生成函数 原根 多项式求逆 多项式开根
    [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp
    [BZOJ1503] [NOI2004]郁闷的出纳员 splay
    [loj#2566][BZOJ5333] [Sdoi2018]荣誉称号 树形dp
    [BZOJ4824][Cqoi2017]老C的键盘 树形dp+组合数
    [BZOJ5305][Haoi2018]苹果树 组合数
    [BZOJ2669][cqoi2012]局部极小值 状压dp+容斥原理
  • 原文地址:https://www.cnblogs.com/flyme/p/4571030.html
Copyright © 2011-2022 走看看