博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#当中的泛型和java中的对比
阅读量:6321 次
发布时间:2019-06-22

本文共 3423 字,大约阅读时间需要 11 分钟。

1.C#中的泛型

先写一个Demo:

namespace generic{        public class Program        {                static void Main(string[] args)                {                        GenericClass
gInt = new GenericClass
(123456);                         Console.WriteLine(gInt.GetType());                        Console.WriteLine(gInt.ToString());                        GenericClass
gStr = new GenericClass
("Test");                        Console.WriteLine(gStr.GetType());                        Console.WriteLine(gStr.ToString());                        Console.Read();                 }        }        //泛型类        public class GenericClass
        {                T _t;                public GenericClass(T t)                {                        _t = t;                }                public override string ToString()                {                        return _t.ToString();                }        }}

 

测试输出:

查看一下IL

C#当中GenericClass<T>是一个泛型类,他和.net中其他的类型一样,同样是一个确定的类型,在不指定情况下,继承自Object类,而且可以进行派生。

与普通类型不同的是,他是一种开放类型,.Net中规定开放类型是不能被实例化的,这就确保了开放类型的泛型参数再被指定之前,不会被实例化成任何对象。

(也没办法,因为也不知道开放类型需要多大的内存)

 GenericClass<string> gStr = new GenericClass<string>("Test");

 GenericClass<int> gInt = new GenericClass<int>(123456);

为开放式的类型提供泛型的实例导致一个封闭类型的产生,他们的关系如下:

上图可以了解到封闭类型和开放类型处于同一层次,而且没有什么关系。

 

综上:C#泛型类在编译时,生成中间代码IL,通用类型T只是一个占位符。在实例化类时,根据用户指定的数据类型代替T并由即时编译器(JIT)生成本地代码,这个本地代码中已经使用了实际的数据类型,等同于用实际类型写的类,所以不同的封闭类的本地代码是不一样的。按照这个原理,我们可以这样认为: 泛型类的不同的封闭类是分别不同的数据类型。 

 

2.JAVA泛型

Java泛型的定义:泛型是JDK1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数,在用到的时候在指定具体的类型。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。

public class Main {        public static void main(String[] args) {                //定义泛型类GenericClass的一个Integer版本                GenericClass
intOb=new GenericClass
(123456);                intOb.ToString();                System.out.println("----------------------------------");                //定义泛型类GenericClass的一个String版本                GenericClass
strOb=new GenericClass
("Test");                strOb.ToString();        }}  class GenericClass
{        private T _t; //定义泛型成员变量        public GenericClass(T t) {                this._t = t;        }        public void ToString() {                  System.out.println(_t.toString());                  }}

结果:

 

C#则是真实的泛型,Java的泛型是伪泛型,怎么理解伪泛型?

正确理解泛型概念的首要前提是理解类型擦出(type erasure)。

Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。

使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉,这个过程就称为类型擦除。

 

如在代码中定义的GenericClass<Integer> GenericClass<String>等类型,在编译后都会编程GenericClassJVM看到的只是GenericClass,而由泛型附加的类型信息对JVM来说是不可见的。

Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。

 

上面代码中执行结果中发现,两个版本的泛型类,都是class com.company.GenericClass,

说明泛型类型StringInteger都被擦除掉了,这个就是所谓的原始类型

 

原始类型(raw type)就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型。

 

综上:

      泛型技术在C#Java之中的使用方式看似相同,但实现上却有着根本性的分歧,C#里面泛型无论在程序源码中、编译后的IL中(Intermediate Language,中间语言,这时候泛型是一个占位符)或是运行期的CLR中都是切实存在的,List<int>List<String>就是两个不同的类型,它们在系统运行期生成,有自己的虚方法表和类型数据,这种实现称为类型膨胀,基于这种方法实现的泛型被称为真实泛型

       Java言中的泛型不一,它只在程序源中存在,在编译后的字节码文件中,就已被替换为原来的原始型(Raw Type,也称型)了,并且在相的地方插入了型代,因此于运行期的Java言来ArrayList<int>ArrayList<String>就是同一个类。所以说泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型

 

转载于:https://www.cnblogs.com/dcz2015/p/5356146.html

你可能感兴趣的文章
Centos 6 编译内核支持LVS-SNAT模式
查看>>
JAVA数据类型
查看>>
TCP segment of a reassembled PDU
查看>>
hdu 5195 DZY Loves Topological Sorting BestCoder Round #35 1002 [ 拓扑排序 + 优先队列 || 线段树 ]...
查看>>
【Oracle】oracle中快速判断某一日期是闰年或平年
查看>>
datatable 转 json 格式
查看>>
vs2010生成Dll文件并引用dll(C#)
查看>>
藏在兰州拉面里精益管理秘诀
查看>>
How to blog on Github
查看>>
百思不得姐 one day
查看>>
19.04.16--指针笔记-参数传递
查看>>
面向对象
查看>>
POJ1860 Currency Exchange
查看>>
关于ST-Link的internal command error问题的解决方法
查看>>
[IDE]VC2012 项目之间依赖关系取消自动Link导致的LNK2019
查看>>
IT兄弟连 JavaWeb教程 Servlet会话跟踪 Cookie路径问题
查看>>
synchronized(this)(转)
查看>>
类别标签处理
查看>>
深度|余凯:基于深度学习的自动驾驶之路
查看>>
ORA-00845: MEMORY_TARGET not supported on this system
查看>>