Java中关于先有鸡还是先有蛋的问题----Class&Object
在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的更多相关文章
- 【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解(转载)
java中的hashcode.equals和toString方法都是基类Object的方法. 首先说说toString方法,简单的总结了下API说明就是:返回该对象的字符串表示,信息应该是简明但易于读 ...
- Java中对比两个对象中属性值[反射、注解]
在Java中通常要比较两个对象在修改前与修改后的值是否相同,一般我们采用的是反射技术获取对象的get方法[或其他的方法]获取值并做比较.如果系统将修改的属性名称也显示出来,这样就能更直观的显示类中的哪 ...
- Java 中 String 的构造方法
String 对于所有 Java 程序员来说都不会陌生,几乎每天甚至每个程序都会和 String 打交道,因此将 String 的常用知识汇集在此,方便查阅. 概叙: Java 中是如此定义 Stri ...
- Java中Object.equals和String.equals的区别详解
前言 Java中的堆和常量池的区别是什么呢?Object.equals与String.equals的区别呢?下面让我们通过一个小示例让你明白它- 1.基础知识 Java的存储空间:寄存器.栈.堆.静态 ...
- Java中JNI的使用详解第五篇:C/C++中操作Java中的数组
在Java中数组分为两种: 1.基本类型数组 2.对象类型(Object[])的数组(数组中存放的是指向Java对象中的引用) 一个能通用于两种不同类型数组的函数: GetArrayLength(ja ...
- 用java实现Simsimi小黄鸡接口
package com.iask.webchat.chatmachine; import java.io.BufferedReader; import java.io.InputStream; imp ...
- Java中值传递和引用传递的区别
在Java中参数的传递主要有两种:值传递和参数传递: 下面是对两种传递方式在内存上的分析: 一:值传递 解释:实参传递给形参的是值 形参和实参在内存上是两个独立的变量 对形参做任何修改不会影响实参 ...
- 浅谈利用同步机制解决Java中的线程安全问题
我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...
- 关于java中指针的概念
今天寡人遇到一个问题,扫描非关系数据库中的图(由node和rel组成),将其转化成由寡人自定义的gnode和gedge组成的图. gnode类包含结点的id,label和包含此gnode的gedge的 ...
随机推荐
- 【DP】POJ 2385
题意:又是Bessie 这头牛在折腾,这回他喜欢吃苹果,于是在两棵苹果树下等着接苹果,但苹果不能落地后再接,吃的时间不算,假设他能拿得下所有苹果,但是这头牛太懒了[POJ另一道题目说它是头勤奋的奶牛, ...
- Linux用户密码重置方法
方法一: 启动时,随便按一个键,空格即可(不能是回车),让其停留在如下界面 按e编辑 在UTF-8后面添加init=/bin/sh init=/bin/sh 根据上面提示,按Ctrl+x启动得下图 输 ...
- extjs4 各种怪异问题
用extjs4 已经有一段时间了,过去开发的时候用过extjs2.2 因为放下了两年所有很多东西记得不是很清楚了,现在又直接使用4 突然发现这个世界变得太快连代码都变得这么快,大部分东西都完全不一样了 ...
- Spring中Bean的作用域
1.在Spring的早期版本中,仅有两个作用域:singleton和prototype,前者表示Bean以单例的方式存在:后者表示每次从容器中调用Bean时,都会返回一个新的实例 2.Spring 2 ...
- git 强制覆盖本地
git fetch --all git reset --hard origin/master git pull 参考:https://ruby-china.org/topics/2494
- 一个修改过简化版的InputQuery
主要是觉得在单输入的情况下, 原来InputQuery输入框左边的文本太难看了...... function _InputQuery(const ACaption: string; const APr ...
- 深入解析PHP中逗号与点号的区别
大部分同学都知道逗号要比点号快,但就是不知道为什么,更不知道逗号与点号这两者之间到底有什么区别.下面小编就来详细的为大家介绍一下,需要的朋友可以过来参考下 echo 'abc'.'def'; //用点 ...
- 使用Ajax异步加载页面时,怎样调试该页面的Js
前言-本人不是干前端的,所以有的名词不专业 在前端中,有时候会遇到这样的框架,http://172.17.11.151:8060/frontend/backend.html#1.html (通过解析U ...
- HTML与CSS
HTML中DTD是什么?是一套关于标记符的语法规则.DTD是一种保证html格式正确最有效的方法.一个DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则. ...
- IIC总线
一. 概述 1. IIC总线是PHILIPS公司推出的一种串口总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串口总线. 2. IIC总线只有两根双向信号线.一根是数据线SDA,一 ...