在Java中,我们常常会看到一个类型:Class。并且在类似Person.class,cache.getClass()等代码中见到它的身影。

众所周知,Class是用来描述一个类的类型,而Object是所有对象的最终父对象。那么就会引申出下边的两个结论:

1、如果从对象的角度来看,那么肯定是先有Object对象,其次才有其派生的对象Class。

2、Class表示的是类、对象,肯定是先有类这个概念,其次才有各个类型(抽象的、非抽象的),包括Object。

这就会出现一个问题,到底是先有Class(鸡)还是先有Object(蛋)?

好吧,此处先给出答案,是先有Object,然后才有Class的。

原因是Object,是所有对象的最终父对象,而Class本身也是一个对象。所以是先有Object,然后才Class对象的。

那么如何解释第二点呢? 这是因为一个概念被混淆了。

在Java中,所有的对象都派生自Object,而Class类(注意此处是大写也是一个类)所以他也继承自Object,这个我们可以在eclipse里边通过查看类的继承关系清楚的看到。

在Java中,还有一个class(注意此处是小写)。他表示的是一个个(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )对象,也就是一个个类。Object是这些对象的其中之一。同时在这些对象中有一个对象,它的作用是用来识别标记其它对象的内容,这个类叫做Class(注意此处是大写)。 因此就会出现有一个class的名字叫做Class。而问题中将class等价于Class,很显然是不合理的。两者完全不在一个维度里。

但是问题还是会出现,在加载Object时(尚未完成加载时),究竟如何实现为其加载对应的Class的呢?这个就涉及到对象最初是如何被系统加载的。这里JVM启动时使用的是C++代码对这些最初的核心类进行表示。分配好内存空间后,互相建立引用,进而才完成类的初始化。所以可以看到如果从JVM实现的角度来说,二者是同时完成加载的。ps 而且面相对象的语言遇到类似的问题,通常也都是通过自举的形式解决最初系统加载顺序的问题(此处蓝色字体感谢@之奇一昂的纠正,原文有偏差已修改)

抛砖引玉----深入学习Class类

了解了class,Object,Class的关系,我们接下来深入说说Class类。(这才是这篇博客的主要目的)

 一、背景知识

类对象在使用之前都会被JVM加载(其实是经过加载、连接、初始化三个步骤对类完成初始化)。类加载指的就是JVM将class文件读入内存,并为之创建一个Class对象。同时当一个类被加载后,再次使用时,就不会被重复加(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )载。这样新建的Class与加载的class就形成一一对应的关系。 通过该Class对象,就可以访问到对应的class。所以我们可以把Class理解为一个类的标识对象,它相当于是一个类的标签(铭牌)。拿到一个Class,我们就可以找到对应的类(class)。

二、获取Class对象的方法

在Java中我们可以使用三个方法拿到Class对象。其中两种是针对已经在家的类对象,去获得他对应的Class对象。剩余一种利用到了反射,根据提供的类名去寻找对应的class文件,进而找到Class对象。

 Class.forName(String className)//className表示完整的名称,包括该类的包名。如果无法找到,该方法会抛出一个
Person.class //Person代表的是一个类,class字段是其默认的属性
person.getClass() //getClass是Obj类的一个实例方法,所有的类都有该方法,包括Class类

三、 从Class中可以获取到的信息

系统可以通过Class对象,找到该对象对应的class.而Class对象包含了class的基本详细信息。这些信息可以分为以下四个方面: 1、获取到class所包含的构造器。 2、获取到class所包含的方法。 3、获取到class所包含的成员变量。 4、获取到class所包含的Annotation。 ps 很多小伙伴可能对Annotation不太熟悉,这里简单说下:Annotation翻译为注解,本身也是一个类,可以用来保存类的描述信息。 有兴趣的可以参考下面这篇文章:

http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

四、在工作中Class类的使用用途

在这里我总结了一下曾经遇到的使用情况,将其分为;两方面,如果有遗漏,大家可以补充。

1、对对象类型的使用和校验

有些时候,我们需要对传入对象的类型进行校验,判断传入的对象是否为我们需要的类型。

if(para.getClass==Person.class)//如果这里使用 instance关键字,则可能会受到Person类继承关系的干扰,导致无法进行正确的判断。 

2、反射

<1>用字符串定义需要加载的类名,然后等到需要时候再加载。

  这样做有三个用途:

  (1)有时候并不知道此处需要加载的类型,需要在运行时才可能知道需要加载哪个class,譬如在运行的过程中,根据用户的手动设置,动态的选择接下来要加载的类。

  (2)在编译时已经知道需要加载的类名,但是尚无需要加载的.class文件,需要在运行时,通过用户上传,或者后台到指定地址下载class文件。   插件化开发的实现就是使用这样一个原理。举两个例子:

      (α)用户在使用过滤时,需要自己来定义一套复杂的过滤机制,这时可能就无法通过界面简单的设置一下需要过滤的内容。可以由用户手动的上传自己的过滤算法的jar包,然后由后台动态的加载,使用该算法。

      (β)亦或者有时候在工作环境中,对于皮肤显示有一套默认的显示效果,同时也支持用户自己上传需要显示效果的jar包。后台拿到用户上传的jar包后,反射出需要用到的特效算法,形成动态的交互。

  (3)缩短编译时间,加快启动软件的速度(包括client 和server)

  在启动时,包含main方法的类被加载,同时它会加载(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )所自己需要的类。这些类再一次加载自己所需要的类。形成递推关系。但是对一个大应用程序来说,整个的启动(加载)过程耗费的时间,常常让用户无法忍受,甚至在还未加载完时就被强制关闭了。

  针对这种情况,我们就可以在main方法类中只加载一些最基本的类。诸如登录、验证等。当登录验证没有问题之后,需要进入业务操作时,才会根据用户的选择,   加载用户需要的类。从而提高软件整体的运行效率和用户体验。

<2>对于工具的开发和使用

当我们开发工具或脚本时,除了使用系统公开的API外,有时还需要用到原有代码中被私有化的一些变量和方法。这时仅仅使用继承是不够的,还需要反射出对象,拿到其中的变量或调用其中的方法。 比如平常使用的UT框架,有时为了测试效率,就提供了很多可以直接调用待测试类私有方法的API。

Java中关于先有鸡还是先有蛋的问题----Class&Object的更多相关文章

  1. 【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解(转载)

    java中的hashcode.equals和toString方法都是基类Object的方法. 首先说说toString方法,简单的总结了下API说明就是:返回该对象的字符串表示,信息应该是简明但易于读 ...

  2. Java中对比两个对象中属性值[反射、注解]

    在Java中通常要比较两个对象在修改前与修改后的值是否相同,一般我们采用的是反射技术获取对象的get方法[或其他的方法]获取值并做比较.如果系统将修改的属性名称也显示出来,这样就能更直观的显示类中的哪 ...

  3. Java 中 String 的构造方法

    String 对于所有 Java 程序员来说都不会陌生,几乎每天甚至每个程序都会和 String 打交道,因此将 String 的常用知识汇集在此,方便查阅. 概叙: Java 中是如此定义 Stri ...

  4. Java中Object.equals和String.equals的区别详解

    前言 Java中的堆和常量池的区别是什么呢?Object.equals与String.equals的区别呢?下面让我们通过一个小示例让你明白它- 1.基础知识 Java的存储空间:寄存器.栈.堆.静态 ...

  5. Java中JNI的使用详解第五篇:C/C++中操作Java中的数组

    在Java中数组分为两种: 1.基本类型数组 2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用) 一个能通用于两种不同类型数组的函数: GetArrayLength(ja ...

  6. 用java实现Simsimi小黄鸡接口

    package com.iask.webchat.chatmachine; import java.io.BufferedReader; import java.io.InputStream; imp ...

  7. Java中值传递和引用传递的区别

    在Java中参数的传递主要有两种:值传递和参数传递: 下面是对两种传递方式在内存上的分析: 一:值传递 解释:实参传递给形参的是值  形参和实参在内存上是两个独立的变量 对形参做任何修改不会影响实参 ...

  8. 浅谈利用同步机制解决Java中的线程安全问题

    我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...

  9. 关于java中指针的概念

    今天寡人遇到一个问题,扫描非关系数据库中的图(由node和rel组成),将其转化成由寡人自定义的gnode和gedge组成的图. gnode类包含结点的id,label和包含此gnode的gedge的 ...

随机推荐

  1. 第 5 章 基础 DOM 和 CSS 操作

    在常规的 DOM 元素中,我们可以使用 html()和 text()方法获取内部的数据.html()方法 可以获取或设置 html 内容,text()可以获取或设置文本内容. $('#box').ht ...

  2. struts基于ognl的自动类型转换需要注意的地方

    好吧,坎坷的过程我就不说了,直接上结论: 在struts2中使用基于ognl的自动类型转换时,Action中的对象属性必须同时添加get/set方法. 例如: 客户端表单: <s:form ac ...

  3. Css3:选择器、字体和颜色样式

    1.私有前缀及其用法 在CSS3模块标准尚未被W3C批准或者标准所提议的特性尚未被浏览器完全实现时,浏览器厂商会使用所谓的私有前缀来测试“试验性的”CSS特性.看看CSS3中实现圆角的代码: .rou ...

  4. 简单的行为控制管理方法,自动登录,session定时验证码过期

    代码很简单 实现的方式很多,用cookies 用static 变量 file文件缓存 等等 比如 //简单行为管理,如果请求此方法次数多于5次,就显示验证码 吧当前方法的name传进来,有效时间是5分 ...

  5. TotalCommander 之 配置

    一.设置配置界面: 1.进入设置界面       点击菜单栏的配置,然后再点击配置里面的选项,便会出现Total Commander设置的界面. 2.设置字体 刚开始,大家会发现这不是我们熟悉的字体啊 ...

  6. 非常适用的Sourceinsight插件,提高效率事半功倍

    一直使用sourceinsight编辑C/C++代码,sourceinsight是一个非常好用的编辑工具可以任意定位,跳转,回退,本人一直 使用该工具做C/C++开发,sourceinsight能够满 ...

  7. new一个JAVA对象的时候,内存是怎么分配的?

    new 对象的时候 在内存中 建立一个 内存区域 就是堆内存 用来存放对象的属性,当new完对象把对象的地址赋给对象的引用变量 这个时候 又在内存中建立一个区域 叫栈内存 用来存储 引用变量 引用变量 ...

  8. jquery on 绑定事件

    jquery on 绑定事件 1. 多个选择器绑定一个事件 2. 多个事件绑定一个函数 3. 一个选择器绑定多个事件,有两种写法: 或者 on只绑定一次事件,绑定父元素,防止初始化时数据未加载,绑定出 ...

  9. bootstrap 部分css样式

    clip: rect(0, 0, 0, 0);剪裁绝对定位元素.outline: 0; cursor: not-allowed;

  10. 【转】C++格式化输出

    在输出数据时,为简便起见,往往不指定输出的格式,由系统根据数据的类型采取默认的格式,但有时希望数据按指定的格式输出,如要求以十六进制或八进 制形式输出一个 整数,对输出的小数只保留两位小数等.有两种方 ...