---恢复内容开始---

目录:

  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类与反射机制的更多相关文章

  1. Java基础复习笔记系列 十三 反射机制

    主题:Java反射机制 学习资料参考网址: 1.http://www.icoolxue.com 1.Java反射机制. 各种框架中都使用到了Java的反射机制. 两个类:java.lang.Class ...

  2. Java 基础之详解 Java 反射机制

    一.什么是 Java 的反射机制?   反射(Reflection)是Java的高级特性之一,是框架实现的基础,定义:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: ...

  3. javase基础复习攻略《一》

    作为一名软件工程专业,JAVA开发方向的大三本科学生,有必要把自己的学到的专业知识进行一下整理,一则方便自己了解自己的学习程度,二则帮助刚刚接触这一门语言的童鞋了解学习,本人来自与河南理工大学,介绍完 ...

  4. 2018年底,IOS面试题的复习之OC的反射机制

    明天要去面试一个公司,今天复习下IOS题目吧 1.说一下OC的反射机制 答:OC的反射机制类似于JAVA的反射机制,这种动态反射机制可以让OC语言更加灵活.这句话是对反射机制的初步认识,具体表现在哪里 ...

  5. 3.JAVA语言基础部分—Class类与反射

    什么是Java反射机制? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的以及动态调用对象的方法的功能称为 ...

  6. javase基础复习攻略《十》

    按照计划本篇为大家总结JAVA的网络编程,什么叫网络编程呢?网络编程!=网站编程,对于这一点大家一定要注意,很多小朋友都曾经这么认为.既然谈到网络编程,咱们先了解一下网络的基础知识,什么是计算机网络? ...

  7. javase基础复习攻略《二》

    今天就开始的真正走进JAVASE的世界,本篇介绍的是:JAVASE基础语法,大家如果有C语言的基础,对于本节内容一定感觉非常轻松,编程语言之间的都是相通的,只不过C语言属于面向过程编程,而JAVA语言 ...

  8. java工厂类与反射机制

    java 简单工厂类 2012-04-22 15:44:07|  分类: java |  标签:java工厂类  简单工厂类  |举报|字号 订阅     简单工厂模式需要由以下角色组成: 接口    ...

  9. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

随机推荐

  1. 服务器ipmi远程管理

    DELL iDRAC (Integrated Dell™ Remote Access Controller )是 Dell PowerEdge 系列服务器上的远程管理方案, 11代 12代服务器已经集 ...

  2. 解决未安装unit测试和jest的Vue项目运行karma start时的错误

    一.起因 在#单元测试#以karma+mocha+chai 为测试框架的Vue webpack项目(一)文中,说明了是对已有的Vue项目进行测试框架的搭建,并进行测试.但是此项目在利用 vue-cli ...

  3. delphi7 打开project/options 出错

    出错提示:Access violation at address 0012F88F. Write of address 0012F88F.然后又提示一条:Access violation at add ...

  4. [18/11/20]break与continue的区别

    一.普通break 和continue 1.break: break用于强行退出循环,不执行循环中剩余的语句. 2.continue continue 语句用在循环语句体中,用于终止某次循环过程,即跳 ...

  5. stn,spatial transformer network总结

    对整篇paper的一个总结:https://blog.csdn.net/xbinworld/article/details/69049680 github:1.https://github.com/D ...

  6. 使用maven创建项目

    http://192.168.4.112/rdmanager/main/index.jhtml 1.对于第一次下载某个项目的源码,按照下面的步骤进行: (1)在D:\projects\目录下的空白位置 ...

  7. js 实现div跟随鼠标移动

    今天看到了一个自己可以随心所欲的拖到div到页面的任意位置.感觉挺好的,就心血来潮的查询了一下,看看网友做的 代码如下: <script>function doit(){ var obj ...

  8. 【洛谷P3119】[USACO15JAN]草鉴定Grass Cownoisseur

    草鉴定Grass Cownoisseur 题目链接 约翰有n块草场,编号1到n,这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草. 贝西总是从1号草场出发,最后 ...

  9. Java并发程序基础

    Thread.stop() 直接终止线程,并且会立即释放这个线程所持有的锁. Thread.interrupt() 并不会是线程立即退出,而是给线程发送一个通知,告知目标线程,有人希望你退出啦,至于目 ...

  10. 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 ...