JavaSE基础复习---Class类与反射机制
---恢复内容开始---
目录:
1、java.lang.class类
2、Java中的反射机制
3、运行时与编译时概念
1. java.lang.class类
Java程序在运行时,Java运行时系统会一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。虚拟机为每种类(型)管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。
获取Class实例的三种方式:
(1)利用对象调用getClass()方法获取该对象的Class实例。通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段
(2)使用Class类的静态方法Class.forName(“类名”),用类的名字获取一个对应的Class实例。此时该类还是源文件阶段,并没有变为字节码文件。
(3)运用类名.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例。当类被加载成.class文件时,此时对应类变成了.class,在获取该字节码文件对象,也就是获取自己类自己,该类处于字节码阶段。
在newInstance()调用类中缺省的构造方法; ObjectnewInstance()(可在不知该类的名字的时候,比如说已经某个类的实例实例),就能实例化一个由此Class对象所标识的对象。
在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。
下面是示例代码:
public calss ClassTest{
public static void main(String[] args)throws Exception{
String str1 = “abc”;
Class c1 = str1.getclass();
Class c2 = Class.forName(“Java.lang.String”);
Class c3 = String.class;
System.out.println(c1==c2 && c1==c3)’
}
}
运行结果是:true。上述例子描述了三种用于获取类的Class对象,事实证明,对于某一个类,JVM只会在内存中产生一份字节码,而这份字节码可以用来产生多个该类实例对象。
Class类的常用方法:
1、getName()
一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
2、newInstance()
Class还有一个有用的方法可以为类创建一个实例,这个方法叫做newInstance()。例如:x.getClass.newInstance(),创建了一个同x一样类型的新实例。newInstance()方法调用默认构造器(无参数构造器)初始化新建对象。同时,如果一个类没有无参的构造函数,则要用以下方法创建实例:
Class c1 = Class.forName(“Reflector.User”);
Constructor constructor = c1.getConstructor(int.class,String.class);
User user = (User)constructor.newInstance(12,”小明”);
在上述代码中,假定User类没有无参的构造函数,则用Class的getConstructor()方法获取好该类的有参构造方法,同时参数列表可以再获取有参构造函数时进行指定。
3、getClassLoader()
返回该类的类加载器。
4、getComponentType()
返回表示数组组件类型的 Class。
5、getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的父类的 Class。
6、isArray()
判定此 Class 对象是否表示一个数组类。
Class的一些小使用技巧:
1、forName和newInstance结合起来使用,可以根据存储在字符串中的类名创建对象。例如:Object obj = Class.forName(A).newInstance();也就创建了类名为s的类的一个实例对象,调用的是s的无参构造函数。
注意,利用Object obj = Class.forName(s).newInstance();来创建A的对象时,等效于用父类引用指向子类实例,obj只能够访问父类子类均有的属性与方法,遵循多态准则,必要时可以将obj强制转换成s类型来使用。
2、虚拟机为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。例如:if(e.getClass() == Employee.class),可以判断,e是否为Employee的实例。
2.Java中的反射机制
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。上面讲过,有三种方法可以获得该类的的Class实例。
通过反射机制可以获得哪些信息?
1. 获取全部构造方法:
下面是获取User类全部构造方法的代码:
2. 获取成员变量并使用Field对象
获取指定成员变量
获取全部成员变量
3. 获得方法并使用Method
Class.getMethod(String, Class...)和Class.getDeclaredMethod(String, Class...)方法,
以获取类中的指定方法,如果为私有方法,则需要打开一个权限:setAccessible(true);用invoke(Object, Object...)可以调用该方法。
同样,也可以一次性获取所有的方法:
4. 获取该类实现的所有接口
Class[ ] cc = User.getInterfaces():确定此对象所表示的类或接口实现的接口
返回值:接口对应的的字节码文件对象的数组
5. 获取指定资源的输入流
InputStream getResourceAsStream(String name)。return:一个 InputStream 对象;如果找不到带有该名称的资源,则返回 null。
参数:所需资源的名称,如果以"/"开始,则绝对资源名为"/"后面的一部分。
6. 动态代理(待补充)
反射机制的应用:
1、利用反射,在泛型为int的ArrayList集合中存放一个String类型的对象。
原理:集合中的泛型只在编译器有效,到了运行期间泛型失效。
2、逆向代码 ,例如反编译
3、与注解相结合的框架 例如Retrofit
4、单纯的反射机制应用框架 例如EventBus 2.x
5、动态生成类框架 例如Gson
反射机制的优缺点:
优点:
运行期类型的判断,动态类加载,动态代理使用反射。
缺点:
性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。
3.运行时与编译时概念
关于java运行时及编译时期的区别:首先我们要了解编译以及运行的概念:编译就是指,编译器帮你把源码翻译成机器能识别的字节码,编译时主要做的事情时检查语法以及优化代码。运行时就是指,代码被加载到内存中,并开始跑起来。
看如下代码:
public class Test{
static final int a=10;
static final int b=20;
int c=10;
int d=20;
public static void main(String[] args){
int num1=a*b; // 第一行int
num2=c*d; //第二行
}
}
可以思考下,第一行跟第二行在编译时期有什么区别?java编译时会做一些优化操作。第一行,因为是两个常量做运算,那么他们的结果就是确定的,即num1的值是确定的。所以在编译时,编译器就会直接算出num1的值。第二行则不会,java在运行时期才为变量分配内存空间。所以反编译后可以得到如下代码:
public static void main (String [] args){
int num1=200;
int num2=c*d;
}
由此,可以证码以上结论。
泛型,重写,重载分别时在运行时还是在编译时期执行?
1.我们知道,泛型的类型检测发生在编译时期,这也正是泛型的好处之一,可以提前暴露问题,而不是等到运行时出现ClassCastException。另外,在检测后编译器会把它重写成实际的对象类型(非泛型类型),这样就可以被JVM执行了,这个过程被称为泛型的擦除。 泛型的擦除关键在于从泛型类型中清楚泛型参数的相关信息,再在必要时添加类型转换和类型检查的方法(例如调用某个泛型方法时,就会执行类型检测)。
泛型的擦除可以简单理解为,将泛型类型java代码转换成为普通代码。泛型擦除的主要过程如下:
1).将所有泛型参数用最左边界(最顶级的父类型)的的类型替换
2).移除所有类型参数
2.方法的重载,重载时在编译时期执行,因为在编译时期如果发生了方法的重载,那么在编译时必须明确具体方法是哪一个
3.方法的重写,重写发生在运行时期。编译时期只会检测父类中是否存在重写的方法,但是并不能明确具体子类的方法。只有在运行时,才知道父子类中到底哪个方法被调用了。这个也被称为运行时多态的体现
参考博文:
https://blog.csdn.net/qq_41907991/article/details/79795382?utm_source=copy
https://blog.csdn.net/u014082714/article/details/50004843
JavaSE基础复习---Class类与反射机制的更多相关文章
- Java基础复习笔记系列 十三 反射机制
主题:Java反射机制 学习资料参考网址: 1.http://www.icoolxue.com 1.Java反射机制. 各种框架中都使用到了Java的反射机制. 两个类:java.lang.Class ...
- Java 基础之详解 Java 反射机制
一.什么是 Java 的反射机制? 反射(Reflection)是Java的高级特性之一,是框架实现的基础,定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: ...
- javase基础复习攻略《一》
作为一名软件工程专业,JAVA开发方向的大三本科学生,有必要把自己的学到的专业知识进行一下整理,一则方便自己了解自己的学习程度,二则帮助刚刚接触这一门语言的童鞋了解学习,本人来自与河南理工大学,介绍完 ...
- 2018年底,IOS面试题的复习之OC的反射机制
明天要去面试一个公司,今天复习下IOS题目吧 1.说一下OC的反射机制 答:OC的反射机制类似于JAVA的反射机制,这种动态反射机制可以让OC语言更加灵活.这句话是对反射机制的初步认识,具体表现在哪里 ...
- 3.JAVA语言基础部分—Class类与反射
什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...
- javase基础复习攻略《十》
按照计划本篇为大家总结JAVA的网络编程,什么叫网络编程呢?网络编程!=网站编程,对于这一点大家一定要注意,很多小朋友都曾经这么认为.既然谈到网络编程,咱们先了解一下网络的基础知识,什么是计算机网络? ...
- javase基础复习攻略《二》
今天就开始的真正走进JAVASE的世界,本篇介绍的是:JAVASE基础语法,大家如果有C语言的基础,对于本节内容一定感觉非常轻松,编程语言之间的都是相通的,只不过C语言属于面向过程编程,而JAVA语言 ...
- java工厂类与反射机制
java 简单工厂类 2012-04-22 15:44:07| 分类: java | 标签:java工厂类 简单工厂类 |举报|字号 订阅 简单工厂模式需要由以下角色组成: 接口 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
随机推荐
- 服务器ipmi远程管理
DELL iDRAC (Integrated Dell™ Remote Access Controller )是 Dell PowerEdge 系列服务器上的远程管理方案, 11代 12代服务器已经集 ...
- 解决未安装unit测试和jest的Vue项目运行karma start时的错误
一.起因 在#单元测试#以karma+mocha+chai 为测试框架的Vue webpack项目(一)文中,说明了是对已有的Vue项目进行测试框架的搭建,并进行测试.但是此项目在利用 vue-cli ...
- delphi7 打开project/options 出错
出错提示:Access violation at address 0012F88F. Write of address 0012F88F.然后又提示一条:Access violation at add ...
- [18/11/20]break与continue的区别
一.普通break 和continue 1.break: break用于强行退出循环,不执行循环中剩余的语句. 2.continue continue 语句用在循环语句体中,用于终止某次循环过程,即跳 ...
- stn,spatial transformer network总结
对整篇paper的一个总结:https://blog.csdn.net/xbinworld/article/details/69049680 github:1.https://github.com/D ...
- 使用maven创建项目
http://192.168.4.112/rdmanager/main/index.jhtml 1.对于第一次下载某个项目的源码,按照下面的步骤进行: (1)在D:\projects\目录下的空白位置 ...
- js 实现div跟随鼠标移动
今天看到了一个自己可以随心所欲的拖到div到页面的任意位置.感觉挺好的,就心血来潮的查询了一下,看看网友做的 代码如下: <script>function doit(){ var obj ...
- 【洛谷P3119】[USACO15JAN]草鉴定Grass Cownoisseur
草鉴定Grass Cownoisseur 题目链接 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后 ...
- Java并发程序基础
Thread.stop() 直接终止线程,并且会立即释放这个线程所持有的锁. Thread.interrupt() 并不会是线程立即退出,而是给线程发送一个通知,告知目标线程,有人希望你退出啦,至于目 ...
- Retain NULL values vs Keep NULLs in SSIS Dataflows - Which To Use? (转载)
There is some confusion as to what the various NULL settings all do in SSIS. In fact in one team whe ...