文档章节

c++模板与java范型的区别。

双月通天
 双月通天
发布于 2016/09/08 17:15
字数 1011
阅读 116
收藏 0

       由于本人之前是c++程序员,现在转行成了java程序员,所以在学习java的时候,感觉和c++很像,特别是java的设计者也曾说,设计这么灵感主要来自于c++,所以看到相似的地方总是要来总结一番的。

1.java泛型的概念

       其实我们在编写类和方法的时候,我们一般使用的是具体的类型(要么是基本的类型,要么是自定义的类,)而用泛型可以使类型参数化,这样就可以编写更通用的代码,可以应用于多种类型的代码。

2.c++模板的概念

       编写带有参数化类型的通用版本,让编译器自动生成针对不同类型的具体版本。

 

       java泛型最主要的目的就是用来指定容器要持有什么类型的对象,而且有编译器来保证类型的正确性。

3.c++模版和java泛型的区别

      3.1c++模板可以使用基本类型(int、short、long),而java泛型不能使用基本类型做类型参数。(为什么)

      3.2.java在使用泛型的时候不会知道具体的类型信息,但是c++是可以知道的。

          因为:java泛型是通过擦除实现的,这意味着你在使用泛型的时候,任何具体的类型信息都没擦除掉了。你唯一知道的就是你在使用一个对象。因此List<string>和List<Interger>在运行时其实是一个类型,两种都会被擦除为其原生的类型List。

          示例 c++

//: generics/Templates.cpp
#include <iostream>
using namespace std;

template<class T> class Manipulator {
  T obj;
public:
  Manipulator(T x) { obj = x; }
  void manipulate() { obj.f(); }
};

class HasF {
public:
  void f() { cout << "HasF::f()" << endl; }
};

int main() {
  HasF hf;
  Manipulator<HasF> manipulator(hf);
  manipulator.manipulate();
} /* Output:
HasF::f()
///:~

这个代码是可以正确运行的,在Manipulator类里面存储了T类型的对象,然后在manipulate里面调用的T对象的f()方法,它是怎么知道f()方法是参数类型T的呢?

   答:当你实例化这个模版的时候,c++编译器将进行检查。他在实例化Manipulator<HasF> manipulator(hf)的这一刻,它看到HasF有一个方法f()。所以c++中,当模版实例化的时候,模板代码知道其模版参数的类型。

但是在java中

class Manipulator<T> {
  private T obj;
  public Manipulator(T x) { obj = x; }
  // Error: cannot find symbol: method f():
  public void manipulate() { obj.f(); }
}

public class Manipulation {
  public static void main(String[] args) {
    HasF hf = new HasF();
    Manipulator<HasF> manipulator =
      new Manipulator<HasF>(hf);
    manipulator.manipulate();
  }
} ///:~

编译会报错,

       因为java编译器无法将manipulator里面的能够在obj上调用f()方法的这一需求映射到HasF拥有f()方法这一事实上。所以java是不知道具体的类型信息的。为了解决这个问题,要使用到泛型边界,以此告知编译器只能接受遵循这个边界的类型。

代码如下

class Manipulator2<T extends HasF> {
    private T obj;
    public Manipulator2(T x) { obj = x; }
    public void manipulate() { obj.f(); }
} ///:~

       边界<T extends HasF> 声明了T是从HasF导出的类型或具有类型HasF,所以就可以在Obj上面调用f()了。

       上面的效果其实就是编译器会把参数类型替换成他的擦除,就像上面的案例。T擦除到了HasF,就好像在类的声明中用HasF替换了T一样。变成如下:

class Manipulator3 {
    private HasF obj;
    public Manipulator3(HasF x) { obj = x; }
    public void manipulate() { obj.f(); }
} ///:~

       使用擦除的原因:擦除的核心动机是它使得泛型化的客户端可以调用非泛型化的类库来使用。反之亦然。其实就是“迁移兼容性”。如果没有某种迁移兼容性,所有已经构建很长时间的类库就需要与希望迁移到java泛型上的开发者们说再见了。类库是很重要的,他们对生产效率会产生重要的影响。因此这不是一个可以接受的代价。

      

        

 

© 著作权归作者所有

双月通天
粉丝 40
博文 280
码字总数 221441
作品 0
徐汇
程序员
私信 提问
献给入门C++/Java选择困难综合症患者

如何让技术群活跃起来?PHP是世界上最好的语言。 没有优秀之分,否则只能显得你不懂另一门语言。如果你想学,那么请远离C/C++,请使用Java,以一个学长的身份,阐述一下。C++向后兼容C,这句...

LoSingSang
2018/12/26
0
0
一 C家族的故事

一 C家族的故事 以下描述摘自《C++对话系列》 “最初,计算机语言非常混乱,高级语言根本不存在,连固定的语言形式也没有。贝尔实验室的Richard Martin在使用了计算机语言的过程中意识到了高...

长平狐
2012/08/28
405
0
浅析:Java与C++的主要区别

Java区别于C++ 表面看来两者最大的不同在于Java没有指针,或者说,Java满地都是指针。对于编程者而言Java的这种设计是安全且更易用的。说Java满地是指针的原因在于它把指针的功能隐藏了,其实...

Ace☞Tseng
2012/10/09
0
0
开源的系统级编程利器:D语言

在Digital Mars公司的D语言首 页上,放置着这样一段话“计算机编程语言门类众多,其来源大致可分为两种途径。一类新语言来自于极具创新精神的学术界;而一类则源于关注研发结合和互联网 的新...

小卒过河
2011/10/11
4.8K
21
JNI和NDK的区别

NDK(Native Development Kit)“原生”也就是二进制 android常用的开发方式是java封装的库,而这些库的底层实现是由C/C++实现,如媒体,图形库等 java调用这样实现就需要用JNI(Java Native...

长平狐
2013/01/06
62
0

没有更多内容

加载失败,请刷新页面

加载更多

【阴阳师】真蛇10层记录

蛇切黑体系 追月神 散件一速,速度越高越好(220+) 镰鼬 招财二速,速度211以上; 山兔 火灵三速,速度180-200均可; 丑女 心眼四速,速度170左右即可; 大蛇 蚌精暴击套。速度高于阴阳师即...

Areya
昨天
4
0
js动态设置元素高度

this.$refs.xxx.style.height= this.contentHeight; 元素需要绑定

Carbenson
昨天
2
0
今天的学习

今天学到了ci框架中的查询语句的where条件语句: 1、$this->db->select('')->from('')->where('id = ??')->get()->result_array();2、$this->db->select('')->from('')->where('id', '??'......

墨冥
昨天
2
0
MySQL在高并发下的订单撮合、系统使用、共享锁与排他锁保证数据一致性

前序 距离上次择文发表,两月余久。2018年也即将要结束了,目前的工作依然是与区块链应用相关的,也很荣幸在9月初受邀签约出版暂名为《区块链以太坊DApp实战开发》一书,预计在明年年初出版。...

我最喜欢三大框架
昨天
2
0
深入理解Flutter多线程

该文章属于<简书 — 刘小壮>原创,转载请注明: <简书 — 刘小壮> https://www.jianshu.com/p/54da18ed1a9e Flutter默认是单线程任务处理的,如果不开启新的线程,任务默认在主线程中处理。 ...

刘小壮
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部