泛型编程之运行期型式信息一

合集下载

Java的泛型详解(一)

Java的泛型详解(一)

Java的泛型详解(⼀)Java的泛型详解泛型的好处编写的代码可以被不同类型的对象所重⽤。

因为上⾯的⼀个优点,泛型也可以减少代码的编写。

泛型的使⽤简单泛型类public class Pair<T> {private T first;private T second;public Pair() {first = null;second = null;}public Pair(T first, T second){this.first = first;this.second = second;}public T getFirst(){return first;}public T getSecond(){return second;}public void setFirst(T first) {this.first = first;}public void setSecond(T second) {this.second = second;}}上⾯例⼦可以看出泛型变量为T;⽤尖括号(<>)括起来,并放在类名后⾯;泛型还可以定义多个类型变量⽐如上⾯的例⼦ first和second不同的类型:public class Pair<T, U> {....}注: 类型变量的定义需要⼀定的规范:(1) 类型变量使⽤⼤写形式,并且要⽐较短;(2)常见的类型变量特别代表⼀些意义:变量E 表⽰集合类型,K和V表⽰关键字和值的类型;T、U、S表⽰任意类型;类定义的类型变量可以作为⽅法的返回类型或者局部变量的类型;例如: private T first;⽤具体的类型替换类型变量就可以实例化泛型类型;例如: Pair<String> 代表将上述所有的T 都替换成了String由此可见泛型类是可以看作普通类的⼯⼚泛型⽅法我们应该如何定义⼀个泛型⽅法呢?泛型的⽅法可以定义在泛型类,也可以定义在普通类,那如果定义在普通类需要有⼀个尖括号加类型来指定这个泛型⽅法具体的类型;public class TestUtils {public static <T> T getMiddle(T... a){return a[a.length / 2];}}类型变量放在修饰符(static)和返回类型的中间;当你调⽤上⾯的⽅法的时候只需要在⽅法名前⾯的尖括号放⼊具体的类型即可;String middle = TestUtils.<String>getMiddle("a", "b", "c");如果上图这种情况其实可以省略,因为编译器能够推断出调⽤的⽅法⼀定是String,所以下⾯这种调⽤也是可以的;String middle = TestUtils.getMiddle("a", "b", "c");但是如果是以下调⽤可能会有问题:如图:可以看到变意思没有办法确定这⾥的类型,因为此时我们⼊参传递了⼀个Double3.14 两个Integer1729 和0 编译器认为这三个不属于同⼀个类型;此时有⼀种解决办法就是把整型写成Double类型类型变量的限定有时候我们不能⽆限制的让使⽤者传递任意的类型,我们需要对我们泛型的⽅法进⾏限定传递变量,⽐如如下例⼦计算数组中最下的元素这个时候是⽆法编译通过的,且编译器会报错因为我们的编译器不能确定你这个T 类型是否有compareTo这个函数,所以这么能让编译器相信我们这个T是⼀定会有compareTo呢?我们可以这么写<T extends Comparable> 这⾥的意思是T⼀定是继承Comparable的类因为Comparable是⼀定有compareTo这个⽅法,所以T⼀定有compareTo⽅法,于是编译器就不会报错了因为加了限定那么min这个⽅法也只有继承了Comparable的类才可以调⽤;如果要限定⽅法的泛型继承多个类可以加extends 关键字并⽤&分割如:T extends Comparable & Serializable限定类型是⽤&分割的,逗号来分割多个类型变量<T extends Comparable & Serializable , U extends Comparable>类型擦除不论什么时候定义⼀个泛型类型,虚拟机都会提供⼀个相应的原始类型(raw type)。

java泛型的高级用法

java泛型的高级用法

java泛型的高级用法
1. 通配符:通配符是泛型中的一种特殊类型参数,使用`?`表示。

通配符可以用于表示任意类型,包括未知的具体类型。

例如,`List<?>`表示一个包含任意类型元素的列表。

2. 上限和下限:上限和下限是在通配符的基础上进一步限制类型的范围。

上限通配符用`<? extends T>`表示,它确保参数类型是`T`或`T`的子类。

下限通配符用`<? super T>`表示,它确保参数类型是`T`或`T`的父类。

3. 类型擦除:尽管在泛型代码中使用了具体的类型参数,但在编译时,泛型信息会被擦除,替换为相应的原始类型。

这是因为 Java 的泛型是通过类型擦除实现的,以保持与早期版本的兼容性。

需要注意的是,在类型擦除后,无法在运行时获取泛型类型参数的具体类型。

4. 泛型方法:除了在类和接口上定义泛型,还可以在方法上定义泛型。

泛型方法允许在调用方法时指定不同的类型参数。

例如,定义一个泛型方法来对不同类型的数组进行排序。

5. 反射和动态泛型:尽管泛型在编译时进行类型检查,但通过反射可以在运行时获取和操作泛型类型信息。

这允许编写一些动态的泛型代码,但需要注意反射操作的性能开销。

6. 自定义泛型类型:除了使用内置的泛型类型如`List`和`Map`,还可以自定义泛型类型。

通过在类或接口上使用泛型参数,可以创建自己的泛型类和接口。

这些是泛型的一些高级用法,它们提供了更大的灵活性和扩展性。

但在实际使用中,需要根据具体需求和代码可读性来决定是否使用泛型的高级特性。

泛型的应用原理

泛型的应用原理

泛型的应用原理什么是泛型泛型是一种编程语言特性,它允许在创建类、接口和方法时指定一种或多种类型作为参数,从而实现代码的复用和类型安全。

泛型在很多编程语言中都有应用,例如Java、C#等。

泛型的作用泛型的主要作用是增加代码的可复用性和类型安全性。

通过使用泛型,我们可以在编写代码时将具体的数据类型作为参数进行传递,从而针对不同的数据类型实现相同的算法或操作。

这样可以避免代码的重复编写,并且在编译期间进行类型检查,减少了在运行时出现类型错误的概率。

泛型的应用场景泛型广泛应用于集合类和算法中。

下面列举了一些常见的泛型应用场景:1.集合类:在集合类中使用泛型可以提供类型安全和代码复用,例如在创建一个List集合时,可以指定集合中元素的类型为某个具体的类,这样可以在编译期间检查添加到集合中的元素的类型是否正确。

2.算法:在算法中使用泛型可以实现对不同数据类型的操作,并且保证类型的安全性。

例如,在排序算法中可以使用泛型来比较不同类型的元素,不同类型的比较操作可以使用重载或实现Comparable接口。

3.接口:在定义接口时可以使用泛型来实现对不同类型的支持。

例如,定义一个泛型接口可以实现对不同类型参数的操作,从而实现代码的重用和类型的安全性。

4.类:在类中使用泛型可以实现对不同类型的支持,例如定义一个泛型的数据结构可以存储不同类型的数据,并且保证类型的安全性。

泛型的工作原理泛型的工作原理是通过类型擦除实现的。

在编译期间,泛型的类型信息会被擦除,编译后的字节码中将不存在泛型的类型信息。

这是为了保持与旧的Java版本的兼容性,并且减少运行时的类型判断。

因此,泛型在运行时是不存在的,只是在编译期间进行类型检查和转换,以保证类型的安全性。

泛型的类型擦除是通过对象的类型参数来实现的。

在创建泛型对象时,需要指定泛型的类型参数,例如List<Integer>表示一个包含整数的列表。

在编译时,类型参数会被替换为其上限或Object类型,例如List<Integer>会被替换为List<Object>。

java 泛型的用法

java 泛型的用法

java 泛型的用法摘要:1.泛型的概念2.泛型的优点3.泛型类型参数4.泛型擦除5.泛型使用实例正文:泛型是Java 中一种强大的功能,它允许我们编写可以处理不同类型的代码,从而提高代码的复用性和类型安全性。

泛型的优点在于它可以让我们的代码更加灵活,不需要针对每个类型都编写特定的方法或类。

在Java 中,泛型是通过在类型后面跟上尖括号<>,然后跟一个或多个类型参数来定义的。

这些类型参数通常使用大写字母表示,如T、E、K、V 等。

类型参数可以有一个或多个,用逗号分隔。

当我们使用泛型时,Java 编译器会进行泛型擦除。

这意味着在编译时,泛型类型参数将被替换为实际的类型。

这样一来,运行时的类型信息就与使用泛型之前一样。

这种擦除可以防止在运行时出现类型不匹配的问题。

下面我们通过一个简单的例子来说明泛型的用法。

假设我们有一个Box 类,用于存储和操作不同类型的对象。

我们可以使用泛型来定义这个类,从而使其可以处理多种类型的数据。

```javapublic class Box<T> {private T content;public Box() {}public Box(T content) {this.content = content;}public T getContent() {return content;}public void setContent(T content) {this.content = content;}}```在上面的代码中,我们定义了一个名为Box 的泛型类,泛型类型参数为T。

Box 类包含一个泛型类型的成员变量content,以及相应的构造函数、getter 和setter 方法。

我们可以使用这个泛型Box 类来存储和操作不同类型的数据,例如:```javaBox<String> stringBox = new Box<>();stringBox.setContent("Hello, world!");String stringContent = stringBox.getContent();System.out.println(stringContent);Box<Integer> integerBox = new Box<>();integerBox.setContent(42);int integerContent = integerBox.getContent();System.out.println(integerContent);```通过使用泛型,我们可以在编译时检查类型安全,并在运行时获得正确的类型信息。

C语言中的泛型编程技术

C语言中的泛型编程技术

C语言中的泛型编程技术
C语言是一种非常强大和灵活的编程语言,但它本身并不直接支持泛型编程。

泛型编程是一种一般化的编程范式,可以提高代码的复用性、可读性和可维护性。

虽然C语言本身并不直接支持泛型编程,但是可以通过一些技术实现相似的效果。

在C语言中,可以使用预处理器的宏来模拟泛型编程的一些特性。

通过定义一些宏和函数来实现泛型数据结构和算法,可以在一定程度上实现泛型编程的效果。

例如,可以定义一些宏来实现通用的数据类型和函数,然后在需要的地方使用这些宏来实现具体的数据结构和算法。

另外,在C语言中也可以通过指针来实现类似泛型编程的效果。

通过使用void 指针和函数指针来实现泛型数据类型和算法,可以在函数调用时传递不同类型的参数。

通过使用void指针来实现泛型数据类型的存储和传递,使用函数指针来实现
泛型算法的调用,可以在一定程度上实现泛型编程的效果。

除了以上两种方法外,还可以使用C语言的内联函数来实现泛型编程。

内联函数是一种特殊的函数,可以在调用处直接展开,从而提高程序的性能。

通过使用内联函数来实现通用的数据结构和算法,可以在一定程度上实现泛型编程的效果。

总的来说,虽然C语言本身并不直接支持泛型编程,但是可以通过一些技术来模拟实现泛型编程的效果。

通过使用预处理器的宏、指针和函数指针、内联函数等方法,可以在C语言中实现一些类似泛型编程的功能,提高代码的复用性、可读
性和可维护性,从而更好地应对复杂的编程需求。

java泛型语法

java泛型语法

java泛型语法Java泛型语法是Java编程语言中的一个重要特性,它允许我们编写更加通用和灵活的代码。

通过使用泛型,我们可以在编译时期检测类型错误,并在运行时期避免类型转换异常。

本文将介绍Java泛型的基本语法和使用方法。

一、泛型的定义和作用泛型是Java中的一种参数化类型,它允许我们在定义类、接口和方法时使用类型参数。

通过使用泛型,我们可以将类型作为参数传递给类、接口和方法,从而实现代码的复用和灵活性。

泛型的作用主要有以下几个方面:1. 类型安全:通过使用泛型,我们可以在编译时期检测类型错误,避免类型转换异常。

2. 代码复用:通过定义泛型类、接口和方法,我们可以实现对多种类型的支持,从而提高代码的复用性。

3. 简化代码:通过使用泛型,我们可以减少冗余的类型转换代码,使代码更加简洁。

4. 提高性能:通过使用泛型,我们可以避免使用Object类型,从而减少了装箱和拆箱的开销,提高了代码的执行效率。

二、泛型的基本语法Java中的泛型通过使用尖括号<>来定义类型参数。

在定义类、接口和方法时,我们可以将类型参数放在尖括号中,并在后续的代码中使用该类型参数。

1. 泛型类的定义:```public class GenericClass<T> {private T data;public T getData() {return data;}public void setData(T data) {this.data = data;}}```在上面的代码中,泛型类GenericClass使用了类型参数T。

我们可以在创建GenericClass对象时指定具体的类型,例如:```GenericClass<String> genericString = new GenericClass<>(); genericString.setData("Hello, World!");String data = genericString.getData();```上面的代码中,我们创建了一个GenericClass对象genericString,并指定了类型参数为String。

java 泛型用法

java 泛型用法

java 泛型用法
Java泛型是指在编写Java程序时,使用泛型类型的技术。

泛型类型是指能够允许在代码中使用不同类型的对象。

Java泛型允许我们在编译时检查我们的代码,以确保类型的安全性,从而避免了运行时类型转换错误。

Java泛型的用法包括以下几种:
1. 泛型类
Java泛型类是一种通用类,可以用来创建其他类的对象。

泛型类可以被定义为一个或多个参数化类型,这些参数化类型被称为类型参数。

使用泛型类时,需要在实例化时指定类型参数。

2. 泛型方法
Java泛型方法是一种通用方法,可以在调用时接受不同类型的参数。

泛型方法可以被定义为一个或多个参数化类型,这些参数化类型被称为类型参数。

使用泛型方法时,需要在调用时指定类型参数。

3. 泛型接口
Java泛型接口是一种通用接口,可以用来创建其他接口的实现。

泛型接口可以被定义为一个或多个参数化类型,这些参数化类型被称为类型参数。

使用泛型接口时,需要在实现时指定类型参数。

4. 通配符
Java泛型的通配符指的是一种可以用来匹配任何类型的占位符。

通配符用?来表示,可以被用来定义泛型类型、方法或接口的参数或返回值类型。

5. 类型边界
Java泛型的类型边界指的是限制泛型类型参数的范围。

类型边界可以被用来定义泛型类型、方法或接口的参数或返回值类型。

通过类型边界,可以限制泛型参数的类型必须是某个类或接口的子类或实现类。

以上是Java泛型的主要用法,掌握这些用法可以有效提高Java 编程效率,以及提高代码的可读性和可维护性。

泛型 方法

泛型 方法

泛型方法泛型方法。

泛型方法是一种在编程中非常重要的概念,它能够帮助我们编写更加灵活、通用的代码。

在本文中,我们将深入探讨泛型方法的定义、特点、以及如何在实际编程中应用泛型方法。

首先,让我们来了解一下泛型方法的定义。

泛型方法是一种在编程中使用类型参数来增加代码的灵活性和通用性的方法。

通过泛型方法,我们可以在方法中使用一个或多个类型参数,从而实现对不同类型的数据进行操作,而无需针对每种类型编写不同的方法。

泛型方法有几个重要的特点。

首先,泛型方法可以与泛型类和泛型接口结合使用,从而实现更加灵活的编程。

其次,泛型方法可以在编译时进行类型检查,从而避免在运行时出现类型错误。

此外,泛型方法还可以减少代码的重复性,提高代码的可维护性和可读性。

在实际编程中,我们可以通过泛型方法来实现对不同类型的数据进行操作。

例如,我们可以编写一个泛型方法来对数组进行排序,而无需针对每种类型的数组编写不同的排序方法。

又如,我们可以编写一个泛型方法来查找数组中的最大值或最小值,而无需针对每种类型的数组编写不同的查找方法。

除此之外,泛型方法还可以应用于集合类中。

通过泛型方法,我们可以实现对不同类型的集合进行操作,从而实现更加灵活和通用的代码。

例如,我们可以编写一个泛型方法来遍历集合中的元素,而无需针对每种类型的集合编写不同的遍历方法。

总之,泛型方法是一种非常重要的编程概念,它能够帮助我们编写更加灵活、通用的代码。

通过泛型方法,我们可以实现对不同类型的数据进行操作,而无需针对每种类型编写不同的方法。

因此,在实际编程中,我们应该充分利用泛型方法,从而提高代码的灵活性、可维护性和可读性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


dynamic_cast
void Company::PayRoll( Employee & e ) // 版本三 { try { Programmer & p = dynamic_cast<Programmer&>( e ); p.PaySalary(); p.PayBonus(); } catch( std::bad_cast ) { e.PaySalary(); } };
TSINGHUA UNIVERSITY

typeid操作符与type_info类
type_info 类
- 编译器实现的动态型式信息型式
- 用于在程序运行时保存数据对象的型式信息 - 不能直接使用该类,只能通过typeid操作符 - 调用成员函数name()可以获得类的名称
typeid 操作符
#include <typeinfo> Programmer p; Employee & e = p; // 输出p实际类名的字符串“Programmer ” cout << typeid(e).name() << endl;
TSINGHUA UNIVERSITY

dynamic_cast
void Company::PayRoll( Employee * e ) // 版本一 { // 调用哪个成员函数?如何区分程序员和经理? e->PaySalary(); e->PayBonus(); };
void Company::PayRoll( Employee * e ) // 版本二 { Programmer * p = dynamic_cast<Programmer*>( e ); if( p ) // p确实指向程序员对象 { p->PaySalary(); p->PayBonus(); } else // p不指向程序员,不发奖金 e->PaySalary(); }; TSINGHUA UNIVERSITY
■பைடு நூலகம்
运行期型式信息
RTTI
- 运行期标识对象的型式信息 - 优势:允许使用指向基类的指针或引用自如地操纵派生类对象
- typeid:获取表达式的型式;type_info:型式信息类
- 头文件:“typeinfo”
对象转型模板
- dynamic_cast:动态转型
- static_cast:静态转型 - reinterpret_cast:复诠转型 - const_cast:常量转型
TSINGHUA UNIVERSITY

dynamic_cast
动态转型的三种方式
- 向上转型:沿着类继承层次向基类转型 - 向下转型:沿着类继承层次向派生类转型
- 交叉转型:沿着类多重继承层次横向转型
指针的动态转型
- 正确执行时,结果为指向目标类对象的指针
- 错误执行时,结果为0/NULL(C++11:nullptr)
引用的动态转型
- 正确执行时,结果为目标类对象的引用
- 错误执行时,引发bad_cast异常
TSINGHUA UNIVERSITY

dynamic_cast
假设软件公司包括程序员和经理两类职员,需要按照不同规 则支付薪水和奖金。如何实现?
class Employee { public: virtual void PaySalary(); virtual void PayBonus(); }; class Manager: public Employee { public: virtual void PaySalary(); virtual void PayBonus(); }; class Programmer: public Employee { public: virtual void PaySalary(); virtual void PayBonus(); }; class Company { public: virtual void PayRoll( Employee * e ); virtual void PayRoll( Employee & e ); private: vector<Employee*> _employees; };
TSINGHUA UNIVERSITY
相关文档
最新文档