当前位置: 首页 > news >正文

怎样办自己的网站查排名

怎样办自己的网站,查排名,科技魏玄成,霸气又聚财的公司名字大全文章目录 第十九章 类型信息1. 为什么需要 RTTI2. Class 对象2.1 Class 对象2.2 类字面常量2.3 泛化的 Class 引用 3. 类型转换检测4. 注册工厂5. 类的等价比较6. 反射:运行时类信息7. 自我学习总结 第十九章 类型信息 RTTI(RunTime Type Information&am…

文章目录

  • 第十九章 类型信息
    • 1. 为什么需要 RTTI
    • 2. Class 对象
      • 2.1 Class 对象
      • 2.2 类字面常量
      • 2.3 泛化的 Class 引用
    • 3. 类型转换检测
    • 4. 注册工厂
    • 5. 类的等价比较
    • 6. 反射:运行时类信息
    • 7. 自我学习总结

第十九章 类型信息

RTTI(RunTime Type Information,运行时类型信息)能够在程序运行时发现和使用类型信息

RTTI 把我们从只能在编译期进行面向类型操作的禁锢中解脱了出来,并且让我们可以使用某些非常强大的程序。

本章将讨论 Java 是如何在运行时识别对象和类信息的。主要有两种方式:

  1. “传统的” RTTI:假定我们在编译时已经知道了所有的类型;

  2. “反射”机制:允许我们在运行时发现和使用类的信息。

1. 为什么需要 RTTI

import java.util.stream.Stream;abstract class Shape {void draw() {// PS:基类中包含 draw() 方法,它通过传递 this 参数传递给 System.out.println() ,// 间接地使用 toString() 打印类标识符System.out.println(this + ".draw()");}@Overridepublic abstract String toString();
}class Circle extends Shape {@Overridepublic String toString() {return "Circle";}
}class Square extends Shape {@Overridepublic String toString() {return "Square";}
}class Triangle extends Shape {@Overridepublic String toString() {return "Triangle";}
}public class Shapes {public static void main(String[] args) {// PS:在把 Shape 对象放入 Stream<Shape> 中时就会进行向上转型(隐式)Stream.of(new Circle(), new Square(), new Triangle()).forEach(Shape::draw);}
}

输出:

Circle.draw()
Square.draw()
Triangle.draw()

严格来说, Stream 实际上是把放入其中的所有对象都当做 Object 对象来持有,只是取元素时会自动将其类型转为 Shape 。这也是 RTTI 最基本的使用形式,因为在 Java 中,所有类型转换的正确性检查都是在运行时进行的。这也正是 RTTI 的含义所在:在运行时,识别一个对象的类型

—PS:多态的应用

2. Class 对象

2.1 Class 对象

Java 使用 Class 对象来实现 RTTI,即便是类型转换这样的操作都是用 Class 对象实现的。

类是程序的一部分,每个类都有一个 Class 对象。换言之,每当我们编写并且编译了一个新类,就会产生一个 Class 对象(更恰当的说,是被保存在一个同名的 .class 文件中)。

所有的类都是第一次使用时动态加载到 JVM 中的,当程序创建第一个对类的静态成员的引用时,就会加载这个类。

其实构造器也是类的静态方法,虽然构造器前面并没有 static 关键字。所以,使用 new 操作符创建类的新对象,这个操作也算作对类的静态成员引用。

因此,Java 程序在它开始运行之前并没有被完全加载,很多部分是在需要时才会加载。这一点与许多传统编程语言不同,动态加载使得 Java 具有一些静态加载语言(如 C++)很难或者根本不可能实现的特性。

一旦某个类的 Class 对象被载入内存,它就可以用来创建这个类的所有对象。

2.2 类字面常量

Java 还提供了另一种方法来生成类对象的引用:类字面常量(

例如:FancyToy.class)。类字面常量不仅可以应用于普通类,也可以应用于接口、数组以及基本数据类型。

当使用 .class 来创建对 Class 对象的引用时,不会自动地初始化该 Class 对象。为了使用类而做的准备工作实际包含三个步骤:

  1. 加载,这是由类加载器执行的

  2. 链接。在链接阶段将验证类中的字节码,为 static 字段分配存储空间,并且如果需要的话,将解析这个类创建的对其他类的所有引用。

  3. 初始化。如果该类具有超类,则先初始化超类,执行 static 初始化器和 static 初始化块。

直到第一次引用一个 static 方法(构造器隐式地是 static )或者非常量的 static 字段,才会进行类初始化。

package typeinfo;import java.util.Random;class Initable {static final int STATIC_FINAL = 47;static final int STATIC_FINAL2 =ClassInitialization.rand.nextInt(1000);static {System.out.println("Initializing Initable");}
}class Initable2 {static int staticNonFinal = 147;static {System.out.println("Initializing Initable2");}
}class Initable3 {static int staticNonFinal = 74;static {System.out.println("Initializing Initable3");}
}public class ClassInitialization {public static Random rand = new Random(47);public static void main(String[] args) throws ClassNotFoundException {// 仅使用 .class 语 法来获得对类对象的引用不会引发初始化Class initable = Initable.class;System.out.println("After creating Initable ref");// 如果一个 static final 值是“编译期常量”(如 Initable.staticFinal ),// 那么这个值不需要对 Initable 类进行初始化就可以被读取System.out.println(Initable.STATIC_FINAL);// PS:对 Initable.staticFinal2 的访问将强制进行类的初始化,因为它不是一个编译期常量,// Initable.staticFinal2 虽然也是用 static final 修饰System.out.println(Initable.STATIC_FINAL2);// 如果一个 static 字段不是 final 的,那么在对它访问时,总是要求在它被读取之前,// 要先进行链 接(为这个字段分配存储空间)和初始化(初始化该存储空间)System.out.println(Initable2.staticNonFinal);//  Class.forName() 来产生 Class 引 用会立即就进行初始化Class initable3 = Class.forName("typeinfo.Initable3");System.out.println("After creating Initable3 ref");System.out.println(Initable3.staticNonFinal);}
}

输出:

After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74

2.3 泛化的 Class 引用

Java 引入泛型语法之后,我们可以使用泛型对 Class 引用所指向的 Class 对象的类型进行限定。在下面的实例中,两种语法都是正确的:

public class GenericClassReferences {public static void main(String[] args) {Class intClass = int.class;Class<Integer> genericIntClass = int.class;genericIntClass = Integer.class; // 同一个东西// 普通的类引用可以重新赋值指向任何其他的 Class 对象intClass = double.class;// 使用泛型限定的类引用只能指向其声明的类型// genericIntClass = double.class;}
}

为了在使用 Class 引用时放松限制,我们使用了通配符,它是 Java 泛型中的一部分。通配符就是 ? ,表示“任何事物”。

public class WildcardClassReferences {public static void main(String[] args) {Class<?> intClass = int.class;intClass = double.class;// 为了创建一个限定指向某种类型或其子类的 Class 引用,// 我们需要将通配符与 extends 关键字配 合使用,创建一个范围限定。Class<? extends Number> bounded = int.class;bounded = double.class;bounded = Number.class;}
}

3. 类型转换检测

直到现在,我们已知的 RTTI 类型包括:

  1. 传统的类型转换,由 RTTI 确保转换的正确性,如果执行了一个错误的类型转换,就会抛出一个 ClassCastException 异常。

  2. 代表对象类型的 Class 对象. 通过查询 Class 对象可以获取运行时所需的信息。

RTTI 在 Java 中还有第三种形式,那就是关键字 instanceof 。它返回一个布尔值,告诉我们对象是不是某个特定类型的实例,可以用提问的方式使用它,就像这个样子:

if(x instanceof Dog) ((Dog)x).bark();

在将 x 的类型转换为 Dog 之前, if 语句会先检查 x 是否是 Dog 类型的对象。进行向下转型前,如果没有其他信息可以告诉你这个对象是什么类型,那么使用 instanceof 是非常重要的,否则会得到一个 ClassCastException 异常。

instanceof 有一个严格的限制:只可以将它与命名类型进行比较,而不能与 Class 对象作比较。

Class.isInstance() 方法提供了一种动态测试对象类型的方法。

Dog.isInstance(x)

4. 注册工厂

工厂方法可以以多态方式调用,并为你创建适当类型的对象。

5. 类的等价比较

当你查询类型信息时,需要注意:instanceof 的形式(即 instanceof 或 isInstance() ,这两者产生的结果相同) 和 与 Class 对象直接比较 这两者间存在重要区别。

class Base {
}class Derived extends Base {
}public class FamilyVsExactType {static void test(Object x) {System.out.println("Testing x of type " + x.getClass());System.out.println("x instanceof Base " + (x instanceof Base));System.out.println("x instanceof Derived " + (x instanceof Derived));System.out.println("Base.isInstance(x) " + Base.class.isInstance(x));System.out.println("Derived.isInstance(x) " + Derived.class.isInstance(x));System.out.println("x.getClass() == Base.class " + (x.getClass() == Base.class));System.out.println("x.getClass() == Derived.class " + (x.getClass() == Derived.class));System.out.println("x.getClass().equals(Base.class)) " + (x.getClass().equals(Base.class)));System.out.println("x.getClass().equals(Derived.class)) " + (x.getClass().equals(Derived.class)));System.out.println("------------");}public static void main(String[] args) {test(new Base());test(new Derived());}
}

输出:

Testing x of type class typeinfo.Base
x instanceof Base true
x instanceof Derived false
Base.isInstance(x) true
Derived.isInstance(x) false
x.getClass() == Base.class true
x.getClass() == Derived.class false
x.getClass().equals(Base.class)) true
x.getClass().equals(Derived.class)) false
------------
Testing x of type class typeinfo.Derived
x instanceof Base true
x instanceof Derived true
Base.isInstance(x) true
Derived.isInstance(x) true
x.getClass() == Base.class false
x.getClass() == Derived.class true
x.getClass().equals(Base.class)) false
x.getClass().equals(Derived.class)) true
------------

instanceof 和 isInstance() 产生的结果相同, equals() 和 == 产生的结果也相同。但测试本身得出了不同的

结论。与类型的概念一致, instanceof 说的是“你是这个类,还是从这个类派生的类?”。而如果使用 == 比较实际的 Class 对象,则与继承无关 —— 它要么是确切的类型,要么不是。

6. 反射:运行时类信息

类 Class 支持反射的概念, java.lang.reflect 库中包含类 Field 、 Method 和 Constructor (每一个都实现了 Member 接口)。这些类型的对象由 JVM 在运行时创建,以表示未知类中的对应成员。然后,可以使用 Constructor 创建新对象, get() 和 set() 方法读取和修改与 Field 对象关联的字段, invoke() 方法调用与 Method 对象关联的方法。此外,还可以调

用便利方法 getFields() 、 getMethods() 、 getConstructors() 等,以返回表示字段、方法和构造函数的对象数组。

RTTI 和反射的真正区别在于,使用 RTTI 时,编译器在编译时会打开并检查 .class 文件。换句话说,你可以 用“正常”的方式调用一个对象的所有方法。通过反射, .class 文件在编译时不可用;它由运行时环境打开并检查。

7. 自我学习总结

  1. RTTI(RunTime Type Information,运行时类型信息)能够在程序运行时发现和使用类型信息

  2. Java 使用 Class 对象来实现 RTTI,保存在 java 文件编译后 .class 文件中

  3. Java 还提供了另一种方法来生成类对象的引用:类字面常量(

    例如:FancyToy.class),此时不会自动初始化该 Class 对象

  4. 使用类前要做到3个步骤:加载(JVM加载类)、链接(为 static 字段分配存储空间)、初始化(初始化超类及 static 修饰的方法和块)

  5. 可以使用泛型对 Class 引用所指向的 Class 对象的类型进行限定:

Class<Integer> genericIntClass = int.class;

​ 通配符与 extends 关键字配合使用,创建一个范围限定:

Class<? extends Number> bounded = int.class;
  1. 类型转换检测:

​ 1)instanceof

if(x instanceof Dog) ((Dog)x).bark();

​ 2)isInstance

Dog.isInstance(x)
  1. instanceof 说的是“你是这个类,还是从这个类派生的类?”(父类或者本类);而如果使用 == 比较实际的 Class 对象,则与继承无关 —— 它要么是确切的类型,要么不是(确切的对象)
http://www.khdw.cn/news/33240.html

相关文章:

  • 微信公众平台开发文档长沙关键词优化服务
  • 新网站怎么做seo优化免费发布平台
  • 商丘整站优化手机流畅优化软件
  • 网站用户粘性怎样在百度上做免费推广
  • 广州靠谱网站建设外包公司武汉seo优
  • 本地东莞网站建设百度推广按点击收费
  • 保定网站制作报价爱站网长尾关键词
  • 做旧工艺品网站营销推广怎么做
  • 做调查问卷赚钱网站有哪些重庆网页搜索排名提升
  • 山东建设工程信息网站深圳seo优化外包
  • 店铺域名是什么意思seo优化是怎么优化的
  • 网站制作的设备环境百度seo优化分析
  • 网站建设教程pdf下载2024年重大新闻简短
  • 台山网站开发seo外链怎么做能看到效果
  • 中国品牌100强排名重庆的seo服务公司
  • 网站架设百度关键词排名突然消失了
  • 某购物网站开发项目唐山seo快速排名
  • 高考写作网站网站建设优化
  • 单页营销网站设计微信scrm系统
  • 无锡做网站需要多少钱天津网络广告公司
  • seo网站系统网站怎么做推广
  • 网页制作与网站建设实战大全pdf大金seo
  • 网站建设冷色调友情链接的形式有哪些
  • 学校网站模板 中文版外贸seo是什么意思
  • 深圳响应样式网站建设费用中央广播电视总台
  • 谷歌网站推广方案100个关键词
  • 互动平台论坛手机优化软件
  • 梧州网站建设电话商丘seo外包
  • 重庆哪家网站今日足球最新预测比分
  • 苏州建站模板厂家百度ocpc如何优化