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

合集下载

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 编程效率,以及提高代码的可读性和可维护性。

泛型 方法

泛型 方法

泛型方法泛型方法。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

java泛型实现原理

java泛型实现原理

java泛型实现原理Java泛型实现原理是Java语言中的一个重要特性,它通过编译器在编译时期对代码进行类型检查和类型推断,确保类型的安全性。

对于泛型的实现原理,可以从以下几个方面进行讨论。

首先,Java泛型是通过使用参数化类型(Parameterized Type)来实现的。

参数化类型是指在声明类型时,在类型名后面添加一对尖括号,用于指定类型参数。

例如,List<String>表示一个存储String类型对象的列表。

通过参数化类型,可以在编译时期确定集合中的元素类型,并且在编译时会进行类型检查。

这是Java泛型实现类型安全的基础。

其次,Java泛型是通过类型擦除(Type Erasure)来实现的。

类型擦除是指在编译时期将泛型类型擦除为其上界或者Object 类型,然后在运行时期进行类型的强制转换。

这是为了兼容Java的旧版本,保证泛型代码可以与非泛型代码一起正常运行。

例如,List<String>在类型擦除后会变为List,因此在运行时期无法获取到泛型的具体类型。

这种通过类型擦除来实现泛型的方式被称为类型安全的擦除(Type-Safe Erasure)。

此外,Java泛型还使用了桥方法(Bridge Method)来支持泛型类型的方法的继承。

桥方法是在编译期生成的,用于在父类和子类之间建立泛型方法的桥梁。

由于类型擦除的存在,子类中的泛型方法在类型擦除后会成为与父类的普通方法签名相同的方法。

为了保持类型的一致性,编译器会在生成子类的字节码时生成桥方法,将子类中的泛型方法转化为桥方法,保证方法的类型安全性和覆盖关系。

另外,Java泛型还使用了限定通配符(Bounded Wildcards)来实现对泛型类型的限制。

通过使用限定通配符,可以对泛型类型的上界或者下界进行限制。

例如,List<? extends Number>表示一个存储Number或其子类对象的列表;List<? super Integer>表示一个存储Integer或其父类对象的列表。

java 泛型的使用规则

java 泛型的使用规则

java 泛型的使用规则Java 泛型是Java 5 引入的一项重要特性,可以让我们在编写代码时更加灵活和安全地处理数据类型。

本文将介绍 Java 泛型的使用规则和一些常见的应用场景。

一、泛型的基本概念泛型是一种参数化类型的机制,它可以让我们在定义类、接口和方法时使用类型参数,从而实现代码的重用和类型的安全检查。

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

二、泛型类的定义和使用在定义一个泛型类时,需要在类名后面加上尖括号(<>),然后在尖括号中指定类型参数。

比如,我们可以定义一个泛型类Box,用来存放任意类型的对象:```public class Box<T> {private T data;public void setData(T data) {this.data = data;}public T getData() {return data;}}```在使用泛型类时,我们需要在实例化对象时指定具体的类型。

例如,我们可以创建一个存放整数的 Box 对象:```Box<Integer> box = new Box<>();box.setData(123);int data = box.getData();```三、泛型方法的定义和使用除了可以在类中定义泛型,我们还可以在方法中使用泛型。

在定义一个泛型方法时,需要在返回值前面加上类型参数。

例如,我们可以定义一个泛型方法 swap,用来交换数组中两个元素的位置:```public <T> void swap(T[] array, int i, int j) {T temp = array[i];array[i] = array[j];array[j] = temp;}```在调用泛型方法时,我们可以显式指定类型参数,也可以通过类型推断自动推断出类型参数。

例如,我们可以交换一个整数数组中两个元素的位置:```Integer[] array = {1, 2, 3, 4, 5};swap(array, 1, 3);```四、通配符的使用通配符是泛型的一种特殊用法,它可以用来表示未知类型或某个范围内的类型。

泛型编程知识点总结

泛型编程知识点总结

泛型编程知识点总结泛型编程的主要优点包括:1. 代码复用性:泛型编程可以使得同一段代码可以适用于多种数据类型,避免了重复编写类似的代码。

2. 类型安全:在泛型编程中,编译器可以对不同数据类型的使用进行类型检查,从而避免了在运行时出现类型错误的问题。

3. 抽象和灵活性:泛型编程可以让开发人员将算法和数据结构进行抽象,从而使得代码更具有通用性和灵活性。

泛型编程的核心概念包括泛型函数、泛型类和泛型接口等。

下面将分别介绍这些内容。

泛型函数泛型函数是使用泛型编程的一种方式。

在泛型函数中,可以使用泛型类型来描述函数参数和返回值的类型。

通过泛型函数,可以实现对不同数据类型的支持,而不必针对每种数据类型编写不同的函数。

下面是一个简单的泛型函数的示例:```javapublic <T> T max(T a, T b) {return pareTo(b) >= 0 ? a : b;}```在这个示例中,<T>表示类型参数,而在函数体中使用了类型参数T来描述参数a和b的类型。

通过这种方式,这个函数可以支持任意可比较的数据类型,而不必针对每种数据类型编写不同的函数。

泛型类除了泛型函数外,泛型编程还支持泛型类。

泛型类是一种可以适用于多种数据类型的类。

在泛型类中,可以使用类型参数来描述类的成员变量和方法的参数和返回值的类型。

下面是一个简单的泛型类的示例:```javapublic class Box<T> {private T data;public void setData(T data) {this.data = data;}public T getData() {return data;}}```在这个示例中,Box类使用了类型参数T来描述数据的类型。

通过这种方式,Box类可以适用于多种数据类型,而不必针对每种数据类型编写不同的类。

泛型接口除了泛型函数和泛型类外,泛型编程还支持泛型接口。

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

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

static_cast
静态转型的用途
- 与dynamic_cast不同,static_cast不仅可用于指针和引 用,还可用于其他型式 - 一般用于非类型式的普通数据对象转型 - 可以在类继承层次上进行向上或向下转型
静态转型的问题
- 不进行运行期型式检查,不安全 - 若转型失败,结果无定义
TSINGHUA UNIVERSITY
TSINGHUA UNIVERSITY

reinterpret_cast
#include <iostream> using namespace std; int f( void* p ) { unsigned int n = reinterpret_cast<unsigned int>( p ); return n; } int main() { int a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int n = f( a ); cout << n << endl; }
TSINGHUA UNIVERSITY

const_cast
常量转型的目的
- 用于取消或设置量的const状态
常量转型的问题
- 如果原始数据对象不能写入,则取消常量修饰可能会导致 未知结果
TSINGHUA UNIVERSITY

const_cast
#include <iostream> class ConstCastTest { public: void SetNum( int num ){ _num = num; } void PrintNum() const; private: int _num; }; void ConstCastTest::PrintNum() const { // 临时取消常量约束,修改目标对象的内容 const_cast<ConstCastTest*>( this )->num--; std::cout << _num; } TSINGHUA UNIVERSITY

Java泛型基础:类型参数与通配符使用

Java泛型基础:类型参数与通配符使用

Java泛型基础:类型参数与通配符使用在Java编程中,泛型是一种强大的机制,允许我们编写更加灵活和可重用的代码。

理解Java中泛型的基础知识是成为一个优秀Java程序员的重要一步。

其中,类型参数和通配符是泛型中的两个重要概念,本文将深入探讨它们的使用。

类型参数类型参数是在定义泛型类、接口或方法时使用的占位符。

通过类型参数,我们可以编写与特定类型无关的代码,并保证程序的类型安全性。

在Java中,类型参数通常用大写字母表示,如T、E等。

类型参数在实例化泛型类或调用泛型方法时被具体类型替换。

泛型类和接口public class Box<T> {private T value;public T getValue() {return value;}public void setValue(T value) {this.value = value;}}上面的代码定义了一个泛型类Box,其中的类型参数T表示可以是任何类型。

通过类型参数T,我们可以创建一个盒子存储任意类型的值。

泛型方法public <T> T getLastElement(List<T> list) {if (list.isEmpty()) {return null;}return list.get(list.size() - 1);}上面的代码定义了一个泛型方法getLastElement,其中的类型参数T表示方法可以操作任何类型的列表,并返回列表中的最后一个元素。

通配符通配符是另一个重要的泛型概念,用于表示未知类型。

通配符是用?表示的,它分为上界通配符<? extends T>和下界通配符<? super T>。

上界通配符上界通配符<? extends T>表示通配符可以接受T类型或T的子类型。

public void printList(List<? extends Number> list) {for (Number n : list) {System.out.println(n);}}上面的代码定义了一个方法printList,接受任何Number类型或其子类型的列表作为参数,实现了对数字类型的通用打印功能。

运行时中的泛型

运行时中的泛型

运⾏时中的泛型当泛型类或泛型⽅法被编译为微软中间语⾔(MSIL)后,它所包含的元数据定义了它的类型参数。

根据所给的类型参数是值类型还是引⽤类型,对泛型类型所⽤的MSIL也是不同的。

当第⼀次以值类型作为参数来构造⼀个泛型类型,运⾏时⽤所提供的参数或在MSIL中适当位置被替换的参数,来创建⼀个专⽤的泛型类型。

[JX3]例如,假设你的程序代码声名⼀个由整型构成的栈,如:Stack<int> stack;此时,运⾏时⽤整型恰当地替换了它的类型参数,⽣成⼀个专⽤版本的栈。

此后,程序代码再⽤到整型栈时,运⾏时复⽤已创建的专⽤的栈。

下⾯的例⼦创建了两个整型栈的实例,它们共⽤⼀个Stack<int>代码实例:Stack<int> stackOne = new Stack<int>();Stack<int> stackTwo = new Stack<int>();然⽽,如果由另⼀种值类型——如长整型或⽤户⾃定义的结构——作为参数,在代码的其他地⽅创建另⼀个栈,那么运⾏时会⽣成另⼀个版本的泛型类型。

这次是把长整型替换到MSIL中的适当的位置。

由于每个专⽤泛型类原本就包含值类型,因此不需要再转换。

对于引⽤类型,泛型的⼯作略有不同。

当第⼀次⽤任何引⽤类型构造泛型类时,运⾏时在MSIL中创建⼀个专⽤泛型类,其中的参数被对象引⽤所替换。

之后,每当⽤⼀个引⽤类型作为参数来实例化⼀个已构造类型时,就忽略其类型,运⾏时复⽤先前创建的专⽤版本的泛型类。

这可能是由于所有的引⽤的⼤⼩都相同。

例如,假如你有两个引⽤类型,⼀个Customer类和⼀个Order类;进⼀步假设你创建了⼀个Customer的栈:Stack<Customer> customers;此时,运⾏时⽣成⼀个专⽤版本的栈,⽤于稍后存储对象的引⽤,⽽不是存储数据。

假如下⼀⾏代码创建了⼀个另⼀种引⽤类型的栈,名为Order:Stack<Order> orders = new Stack<Order>();和值类型不同,运⾏时并没有为Order类型创建另⼀个栈的专⽤版本。

java泛型用法

java泛型用法

java泛型用法
Java中的泛型是一种参数化类型的机制,它允许在定义类、接口和方法时使用类型参数,以增加代码的通用性和安全性。

泛型的用法包括以下几个方面:
1. 泛型类:使用`<T>`或其他类型参数来定义一个类,T表示类型参数,可以在类中的字段、方法的参数和返回值等地方使用T来表示一个具体的类型。

例如:`class MyGenericClass<T> {}`
2. 泛型接口:与泛型类类似,可以使用类型参数来定义接口。

例如:`interface MyGenericInterface<T> {}`
3. 泛型方法:在方法的返回类型之前使用`<T>`或其他类型参数来定义一个方法,该方法可以在调用时指定具体的类型参数。

例如:`<T> T myGenericMethod(T parameter) {}`
4. 通配符:使用`?`作为类型参数,表示不确定的类型。

例如:`List<?> list`表示可以存储任何类型的元素的列表。

5. 上界限定和下界限定:通过使用`extends`和`super`关键字,可以对泛型类型进行上界限定(只能是某个特定类型或其子类型)或下界限定(只能是某个特定类型或其父类型)。

6. 类型擦除:泛型在编译时会进行类型擦除,即泛型类型会被擦除为其上界或Object类型。

这意味着在运行时无法获取泛型的具体类型信息。

使用泛型可以提高代码的灵活性和安全性,能够在编译时进行类型检查,减少类型转换的错误和异常。

同时,它也使得代码更具有可读性和可维护性。

C语言的类型推断与泛型编程

C语言的类型推断与泛型编程

C语言的类型推断与泛型编程概述在C语言中,类型推断和泛型编程是两个重要的概念。

类型推断可以帮助开发者省略类型声明,让代码更加简洁和易读。

而泛型编程则允许我们编写可复用的代码,不受具体类型的限制。

本文将介绍C语言中的类型推断和泛型编程的基本概念和使用方法。

类型推断什么是类型推断类型推断是指编译器能够根据上下文自动推断出变量或表达式的类型,而不需要显式地声明。

C语言中,类型推断主要通过初始化操作来实现。

当我们给变量赋值时,编译器会根据赋值的类型来推断出变量的类型。

使用类型推断的好处使用类型推断可以减少代码中的冗余和重复,使代码更加简洁和易读。

由于不再需要显式地声明变量的类型,我们能够更加专注于代码的逻辑,而不需要分心去关注类型声明。

示例下面是一个使用类型推断的示例:int num = 10; // 显式声明一个int类型的变量auto num2 = 10; // 使用类型推断,编译器会自动推断出num2的类型为int 泛型编程什么是泛型编程泛型编程是一种编程范式,它允许我们编写可复用的代码,而不受具体类型的限制。

在C语言中,我们可以使用宏定义或者函数指针来实现泛型编程。

使用泛型编程的好处使用泛型编程可以使代码更加灵活和通用。

通过编写具有泛型特性的代码,我们可以减少代码的重复,提高代码的复用性和可维护性。

示例下面是一个使用泛型编程的示例:#define MAX(x, y) (((x) > (y)) ? (x) : (y)) // 使用宏定义实现泛型的最大值函数int max_num = MAX(10, 20); // 调用宏定义,编译器会自动将表达式展开为(((10) > (20)) ? (10) : (20))float max_float = MAX(3.14, 2.718); // 同样的宏定义可以用于不同类型的参数总结通过本文的介绍,我们了解了C语言中的类型推断和泛型编程的基本概念和使用方法。

Java语言泛型编程最佳实践

Java语言泛型编程最佳实践

Java语言泛型编程最佳实践Java中的泛型编程是一种强大的编程技术,可以提高代码的安全性和可读性。

在本文中,我们将探讨Java泛型编程的最佳实践,以及一些常见的使用技巧。

一、为什么使用泛型编程泛型编程使得我们能够创造出更加通用和灵活的代码。

它可以在编译期间检查类型,并提供类型安全性。

使用泛型,我们可以在编写代码时指定参数类型,然后编译器会将这些类型检查和转换任务代为完成,这样就可以减少运行时错误的可能性。

泛型编程还可以提高代码的可读性和可维护性。

通过使用泛型,我们可以在代码中明确声明参数类型,这样其他开发人员在使用我们的代码时就可以很清楚地知道预期的类型,并且可以更好地理解代码的意图。

二、泛型类和接口在Java中,我们可以通过定义泛型类和泛型接口来实现泛型编程。

1. 定义泛型类泛型类是一种具有类型参数的类。

我们可以在类名后面使用尖括号来指定类型参数,然后在类的成员变量和方法中使用这些类型参数。

下面是一个泛型类的示例:```javapublic class MyGenericClass<T> {private T value;public void setValue(T value) {this.value = value;}public T getValue() {return value;}}```在上述示例中,我们使用类型参数 `T` 来表示一个占位符类型。

在实例化这个类时,我们可以指定具体的类型,例如`MyGenericClass<Integer>` 或者 `MyGenericClass<String>`。

2. 定义泛型接口泛型接口和泛型类类似,可以通过使用类型参数来定义接口的方法和成员变量。

下面是一个泛型接口的示例:```javapublic interface MyGenericInterface<T> {void doSomething(T value);}```在上述示例中,接口 `MyGenericInterface` 使用类型参数 `T` 来定义了一个抽象方法 `doSomething`。

Java泛型函数的运行时类型检查的问题

Java泛型函数的运行时类型检查的问题

Java泛型函数的运⾏时类型检查的问题在⼀个数据持久化处理中定义了数据保存和读取的泛型函数的,但是在运⾏时出现类型转换错误,类型不匹配,出错的位置不是load⽅法,⽽是在调⽤load⽅法之后,得到了列表数据,对列表数据进⾏使⽤时出现的。

结果列表⾥⾯的元素实际是A类型,调⽤load⽅法传递的是B类型的class,但是仍然load成功。

很是疑惑,最终修改代码调试后,解决问题。

import android.content.Context;import android.text.TextUtils;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.ObjectInputStream;import java.util.ArrayList;/*** 从私有⽂件加载对象* @param context* @param key 键值(⽂件名)* @return*/public static Object loadFromPrivateFile(Context context, String key) {if (context == null || TextUtils.isEmpty(key)) {return null;}ObjectInputStream objectIn = null;Object result = null;try {FileInputStream fileIn = context.openFileInput(key);objectIn = new ObjectInputStream(fileIn);result = objectIn.readObject();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {if (objectIn != null) {try {objectIn.close();} catch (IOException e) {}}}return result;}/*** 加载实体对象* @param context* @param key 键值(⽂件名)* @param clazzOfT 类类型*/public static <T> T loadEntityObject(Context context, String key, Class<T> clazzOfT) {Object object = loadFromPrivateFile(context, key);if (object != null && clazzOfT != null && clazzOfT.isInstance(object)) {return clazzOfT.cast(object);}try {return (T) clazzOfT.newInstance();} catch (Exception e) {e.printStackTrace();}return null;}/*** 加载数组列表* @param context* @param key 键值(⽂件名)* @param clazzOfT 类类型* @return*/@SuppressWarnings("unchecked")public static <T> ArrayList<T> loadArrayList(Context context, String key, Class<T> clazzOfT) {Object object = loadFromPrivateFile(context, key);if (object instanceof ArrayList<?>) {try {return (ArrayList<T>)object;} catch (Exception e) {}}return null;}/*** 加载数组列表* @param context* @param key 键值(⽂件名)* @param clazzOfT 类类型* @return*/@SuppressWarnings("unchecked")public static <T> ArrayList<T> loadArrayList2(Context context, String key, Class<T> clazzOfT) {ArrayList<T> result = null;Object object = loadEntityObject(context, key, Object.class);if (object instanceof ArrayList<?>) {result = new ArrayList<T>();ArrayList<?> list = (ArrayList<?>)object;try {final String className = clazzOfT. getName();for (Object item : list) {if (item. getClass().getName().equals(className)) {result. add((T)item);}}} catch (Exception e) {e.printStackTrace();}}return result;}loadArrayList⽅法是错误的实现,下⾯的loadArrayList2是正确的实现。

java泛型的作用和实现原理

java泛型的作用和实现原理

java泛型的作用和实现原理
Java泛型的作用是提高代码的复用性、类型安全性和可读性。

它允许开发人员在编写代码时指定一种或多种类型参数,并在编译时检查这些参数是否正确使用。

泛型可以应用于类、接口、方法和数组等数据结构,使代码更加灵活和通用。

实现原理:
Java的泛型是通过类型擦除的机制来实现的。

在编译时,泛型信息会被擦除,并且所有的泛型类型都会被转换为它们的限定类型或Object类型。

在使用泛型类型时,Java编译器会进行类型替换,使得泛型类型的具体实例与对象类型相符。

这种类型替换发生在编译过程中,而不是运行时。

例如,当声明一个ArrayList<Integer>时,编译器会将其替换为ArrayList<Object>,并在编译时进行类型检查。

类型擦除的实现原理在编译时引入了一些桥方法和类型转换。

桥方法是生成的额外方法,用于在父类和子类之间进行调用,以保持多态性和类型安全性。

类型转换在运行时进行,以确保泛型类型的有效性。

类型擦除的实现原理使得泛型类型在运行时成为了原始类型,因此无法获得实际的泛型类型信息。

这也导致了一些局限性,如无法使用基本类型作为泛型参数、不能在运行时获取泛型的具体类型等。

总之,Java的泛型通过类型擦除的机制来实现,提供了一种在编写代码时指定类型参数的方式,增加了代码的灵活性和通用性。

虽然泛型在运行时失去了具体的类型信息,但在编译时进行类型检查和类型替换,使得代码更加安全和可读。

scala之泛型详解

scala之泛型详解

scala之泛型详解Scala是一种运行在Java虚拟机上的高级静态类型编程语言,它提供了强大且灵活的泛型机制。

泛型是指在编程语言中定义类、函数或接口时,可以使用类型参数来代表具体的类型。

通过使用泛型,我们可以编写更加通用和可复用的代码,同时还能提高代码的安全性和性能。

在Scala中,泛型可以应用于类、函数和方法。

通过在类或方法的定义中使用泛型参数,我们可以将类型的具体实现推迟到使用该类或方法的时候才确定。

这使得我们可以编写更加通用的代码,而不必为每种类型都重新编写一遍。

在类的定义中使用泛型的语法是在类名后面用方括号括起来的一个或多个类型参数。

例如,我们可以定义一个泛型的容器类来存储任意类型的对象:```class Container[T](value: T) {def getValue: T = value}```在上面的例子中,`Container`类有一个类型参数`T`,它表示容器中存储的值的类型。

`value`字段的类型被定义为`T`,并且在`getValue`方法的返回类型中也使用了`T`。

这样,我们就可以创建一个存储任意类型值的容器,例如:```val container1 = new Container[String]("Hello")val container2 = new Container[Int](42)```在函数和方法的定义中使用泛型的语法与类类似。

我们可以使用方括号括起来的类型参数列表来定义泛型参数,并在函数或方法的签名中使用它们。

例如,我们可以定义一个泛型的`filter`函数来过滤列表中的元素:```def filter[T](list: List[T], predicate: T => Boolean): List[T] = {list.filter(predicate)}```在上面的例子中,`filter`函数有两个类型参数`T`和`U`,分别表示列表中的元素类型和谓词函数的参数类型。

相关主题
  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
相关文档
最新文档