Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java泛型,支持“;专业化;?与C+的概念相似性+;模板?_Java_C++_Generics_Template Specialization - Fatal编程技术网

Java泛型,支持“;专业化;?与C+的概念相似性+;模板?

Java泛型,支持“;专业化;?与C+的概念相似性+;模板?,java,c++,generics,template-specialization,Java,C++,Generics,Template Specialization,我知道很多如何使用C++模板,请注意,我不是专家。对于Java泛型(以及Scala),我有自己的困难。也许是因为我试图把我的C++知识翻译成java世界。我在别处读到,“它们没有什么相似之处:java泛型只是语法省糖的转换,C++模板只是一个美化的预处理器”:-( 我很确定,这两种观点都有点简化。因此,为了理解大的差异和细微的差异,我尝试从专业化开始: 在C++中,我可以设计一个模板(函数类),该模板作用于支持我所需操作的任何类型的T: template<typename T> T

我知道很多如何使用C++模板,请注意,我不是专家。对于Java泛型(以及Scala),我有自己的困难。也许是因为我试图把我的C++知识翻译成java世界。我在别处读到,“它们没有什么相似之处:java泛型只是语法省糖的转换,C++模板只是一个美化的预处理器”:-(<)/P> 我很确定,这两种观点都有点简化。因此,为了理解大的差异和细微的差异,我尝试从专业化开始:

C++中,我可以设计一个模板(函数类),该模板作用于支持我所需操作的任何类型的
T

template<typename T>
T plus(T a, T b) { return a.add(b); }
即使所有其他类型仍然可以使用“默认”实现,现在我为
MyX
添加了一个特殊的实现——没有运行时开销

是否存在具有相同用途的Java泛型机制?当然,在编程中,一切都是可行的,但我的意思是,从概念上讲,没有任何技巧和魔术?

java泛型,它与C++模板不同。 例如:

Java代码:

 public <T> T sum(T a, T b) {
  T newValue = a.sum(b);
  return newValue;
 }
publictsum(ta,tb){
T newValue=a.和(b);
返回新值;
}
在java中,这段代码不起作用,因为泛型的基类是java.lang.Object,所以只能使用这个类的方法

您可以这样构造此方法:

public <T extends Number> T sum(T a, T b) {
  T newValue = a.sum(b);
  return newValue;
 } 
public Object plus(Object that) {
    return this.plus((Integer)that);
}
public static <T extends Addable<T>> product (int times, T factor) {
    T result = factor;
    while(n > 1) {
        result = sum(result, factor);
    }
    return result;
}
publictsum(ta,tb){
T newValue=a.和(b);
返回新值;
} 
在本例中,泛型的基础是类java.lang.Number,因此可以使用整数、双精度、长ecc

方法“sum”取决于java.lang.Number的实现


再见

否-但您的特定问题更像是一个过载问题

定义2个
加上
这样的方法是没有问题的

<T extends Addable> 
T   plus(T   a, T   b) { .. }

MyX plus(MyX a, MyX b) { .. }
如果每个
Si
都是
Ti

对于泛型类,我们可以

class C<T extends Number> { ... }

class C_Integer extends C<Integer>{ ... } 
C类{…}
类C_Integer扩展了C{…}
调用者必须使用
C_Integer
而不是
C
来选择“专用”版本



关于duck类型:Java在静态类型方面更严格——除非它是duck,否则它不是duck

不,Java中的泛型不是这样工作的

有了泛型,你就不能做任何没有泛型就不可能做的事情——你只需要避免编写大量的强制转换,并且编译器确保一切都是类型安全的(只要你没有得到一些警告或抑制这些警告)

因此,对于每个类型变量,您只能调用在其边界中定义的方法(没有duck类型)

此外,没有代码生成(除了一些适配器方法,为了实现泛型类型,可以将它们委托给具有其他参数类型的方法)。假设你有这样的东西

/**
 * interface for objects who allow adding some other objects
 */
interface Addable<T> {
   /** returns the sum of this object and another object. */
   T plus(T summand);
}
静态方法编译为相同的字节码,如下所示(注释中包含其他类型信息):

这称为类型擦除

现在可以为可添加类型的每对两个元素调用此方法,如下所示:

public class Integer implements Addable<Integer> {
    public Integer plus(Integer that) {
       return new Integer(this.value + that.value);
    }

     // private implementation details omitted
}
此方法将仅由具有正确类型的泛型代码调用,这保证了编译器,假设您没有在某处执行一些不安全的强制转换-那么这里的
(Integer)
强制转换将捕获错误(并抛出ClassCastException)

sum
方法现在总是调用第一个对象的
plus
方法,没有办法解决这个问题。没有可能为每种类型的参数生成代码(这个<强> < /强> java泛型与C++模板之间的关键区别),因此不能简单地用专门的方法替换生成的方法之一。 当然,您可以创建第二个
sum
方法,如unreputable proposed(带重载),但只有在直接在源代码中使用
MyX
类型时,才会选择此方法,而不是在从其他一些碰巧用MyX参数化的通用代码调用
sum
方法时,例如:

public <T extends Number> T sum(T a, T b) {
  T newValue = a.sum(b);
  return newValue;
 } 
public Object plus(Object that) {
    return this.plus((Integer)that);
}
public static <T extends Addable<T>> product (int times, T factor) {
    T result = factor;
    while(n > 1) {
        result = sum(result, factor);
    }
    return result;
}
公共静态乘积(整数倍,T系数){
T结果=因子;
而(n>1){
结果=总和(结果、系数);
}
返回结果;
}
现在,
product(5,新的MyX(…)
将调用我们的
sum(T,T)
方法(它反过来调用
plus
方法),而不是任何重载的
sum(MyX,MyX)
方法


(JDK 7添加了一个新的
动态
方法分派模式,该模式允许在运行时通过每个参数进行专门化,但Java语言不使用这种模式,只打算由其他基于JVM的语言使用。)

类型擦除的方法应为
可加和(可加第一,可加第二)
非常好地解释了泛型如何用于
sum
。现在我可以将其转化为我的旧Java知识。但这里删除的是什么?“类型擦除”是指什么?当然!通过重载进行专门化。我真是太蠢了:-)那太蠢了。Thx@towi:“类型擦除”是指将每个泛型类型(可能是参数化类型、泛型数组类型或类型变量)转换为非泛型类型的过程,因为VM只能直接处理这些类型。请参阅JLS中的部分。这只是重载,如果使用
T
从某些通用方法调用
plus
方法,并使用
MyX
调用,则此方法无效。
public static <T extends Addable<T>> product (int times, T factor) {
    T result = factor;
    while(n > 1) {
        result = sum(result, factor);
    }
    return result;
}