据我所知,在Java中,例如,C#泛型是编译时功能,并通过类型擦除删除.那么,Gson TypeToken的确如何运作?它是如何获得对象的泛型类型的?
我有scala函数,如下所示:
现在,根据T的类型(在我的情况下,它可以是Double,Boolean和LocalDate),我需要应用函数ob.像这样的东西(我知道代码没有任何意义,但我想传达我的意思):
def X[T](ob: Observable[T]): Observable[T] = {
//code
T match {
case Double => DoSomething1(ob:Observable[Double]):Observable[Double]
case Boolean => DoSomething2(ob:Observable[Boolean]):Observable[Boolean]
case LocalDate => DoSomething3(ob:Observable[LocalDate]):Observable[LocalDate]
}
}
Run Code Online (Sandbox Code Playgroud)
考虑到Scala的Erasure属性,可以用某种方式反射来完成工作吗?它甚至可能吗?
我想有一个compareTo方法,它接受一个Real(一个用于处理任意大而精确的实数的类[好吧,只要它的长度小于2 ^ 31])和compareTo方法一个对象,但Java不让我,我没有足够的经验知道为什么.
我只是尝试修改类来实现Comparable,我在下面收到了这些错误消息.我真的不明白错误信息是什么意思,但我知道它与可怕的方式有关,我试图给我们的课程一些灵活性,为我制作的每一种方法提供所有不同的方法签名,我可以修复它通过删除compareTo(Object other)方法,但我最好保留它.所以我真正要问的是:有没有办法让这些错误消息消失而不删除compareTo(Object other)方法,这些错误究竟是什么意思?
另外,我知道已经有一些像BigInteger这样的内置Java类,以及我正在尝试使用这个类的东西,但我正在为了与Project Euler(https://一起使用)的乐趣/满足而这样做projecteuler.net/).
Jake@Jake-PC /cygdrive/c/Users/Jake/Documents/Java/Mathematics
$ javac Real.java
Real.java:377: error: name clash: compareTo(Real) in Real overrides a method whose erasure is the same as another method, yet neither overrides the other
public int compareTo(Real other)
^
first method: compareTo(Object) in Real
second method: compareTo(T) in Comparable
where T is a type-variable:
T extends Object declared in interface Comparable
Real.java:440: error: name clash: compareTo(Object) in Real and compareTo(T) in Comparable have the …Run Code Online (Sandbox Code Playgroud) 我想问一下java类型的擦除规则.
如果我们有课程:
public class Shape{}
public class Circle extends Shape{}
public class Base<T extends Shape>{
T x;
public void setX(T t){}
}
public class MainClass(){
public static void main(String... _arg){
Base<? extends Shape> bs = new Base<Circle>();
bs.setX(new Circle()); // <- compilation problem
}
}
Run Code Online (Sandbox Code Playgroud)
你能解释一下为什么调用setX()方法会导致编译问题吗?
在研究另一个问题时,我碰到了1.8.0_112 Sun-Oracle编译器的这种有趣行为(我没有和其他人一起测试过):
import java.util.List;
interface Alpha<T> {
List<Integer> intList();
}
interface Beta {
List<Integer> intList();
}
class Main {
public static void main(String[] args) {
Alpha rawAlpha = null;
Alpha<Character> charAlpha = null;
Alpha<?> qmAlpha = null;
Beta beta = null;
for (Integer i : charAlpha.intList()) {}
for (Integer i : qmAlpha.intList()) {}
for (Integer i : beta.intList()) {}
for (Integer i : rawAlpha.intList()) {}
}
}
Run Code Online (Sandbox Code Playgroud)
编译器仅在最后一个for循环中失败:
error: incompatible types: Object cannot be converted to …Run Code Online (Sandbox Code Playgroud) 我正在研究这一时期的仿制药,今天我已经为我找到了这个谜.
让我们考虑以下虚拟类:
public class Main{
public static void main(String[] args) {
Container<Integer> c = new Container<Integer>();
c.getArray(); //No Exception
//c.getArray().getClass(); //Exception
//int a = c.getArray().length; //Exception
}
}
class Container<T> {
T[] array;
@SuppressWarnings("unchecked")
Container() {
array = (T[])new Object[1];
}
void put(T item) {
array[0] = item;
}
T get() { return array[0]; }
T[] getArray() { return array; }
}
Run Code Online (Sandbox Code Playgroud)
由于擦除,在运行时,getArray()方法的T []返回类型变为Object [],这对我来说是完全合理的.
如果我们按原样访问该方法(c.getArray())没有抛出异常,但是如果我们尝试在返回的数组上调用某些方法,例如c.Array().getClass(),或者如果我们尝试访问一个字段,例如c.getArray().length,然后抛出以下异常:
线程"main"中的异常java.lang.ClassCastException:[Ljava.lang.Object; 无法转换为[Ljava.lang.Integer;
为什么抛出此异常?为什么不对简单的c.getArray()调用抛出它?如果我们只是调用getClass()或访问长度,它为什么要尝试强制转换为Integer []?对于[],getClass()和长度是否也不可用?
在此先感谢您的许多(我希望)和解释(我也希望这样)答案.
在使用Kotlin/Java进行编码时,我在使用强制转换和泛型时偶然发现了一些奇怪的东西.似乎有可能让类型系统认为列表是类型List<Foo>,而它实际上是一个List<Object>.
任何人都可以向我解释为什么这是可能的?
以下是Kotlin和Java中的一个例子:
Kotlin中的例子
fun <T> test(obj: Any): List<T> {
val ts = ArrayList<T>()
ts.add(obj as T)
return ts
}
fun <T> test2(obj: Any): T {
return obj as T
}
fun <T> test3(obj: Any): List<T> {
val ts = ArrayList<T>()
ts.add(test2(obj))
return ts
}
fun main(args: Array<String>) {
val x = test<Double>(1) // Returns a list of Integers and doesn't error
println(x)
val y = test2<Double>(1) // Casts the Int object to a Double.
println(y) …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
object Log {
def get[T](implicit manifest : Manifest[T] ) = {
LoggerFactory.getLogger( manifest.erasure.getName )
}
def getByName( name : String ) = {
LoggerFactory.getLogger(name)
}
}
Run Code Online (Sandbox Code Playgroud)
想法是这样使用它:
object SimpleFuture {
val log = Log.get[SimpleFuture[Throwable,Nothing]]
}
Run Code Online (Sandbox Code Playgroud)
但编译器(2.10)现在表示manifest.erasure已弃用.我现在应该使用什么来实现相同的功能?
我正在为jdk6阅读令人难以置信的书"java scjp认证的程序员指南",以及关于泛型覆盖的部分.在它上面描述了subsignature和override-equivalent,并描述了一些我引用的覆盖等价的例子:
给定以下三个类中的泛型方法声明:
static <T> void merge (MyStack<T> s1, MyStack<T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? extends T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? super T> s2) { /*...*/ }在擦除之后,所有三种方法的签名是:
merge(MyStack, MyStack)即,方法的签名是覆盖等价的,因此这些方法不会过载.
我并不完全同意这些方法是覆盖等价的,事实上我认为这些方法有一个"擦除名称冲突",但没有一个是另一个的子签名...可能我错了所以我想对此有所了解.
子签名的定义让我觉得它们不是它们之间的子签名.
在JSL 6#8.4.2方法签名中(http://docs.oracle.com/javase/specs/jls/se6/html/classes.html#8.4.2)
如果两个方法具有相同的名称和参数类型,则它们具有相同的签名.如果满足以下所有条件,则两个方法或构造函数声明M和N具有相同的参数类型:
他们.具有相同数量的形式参数(可能为零)
它们具有相同数量的类型参数(可能为零)
让我们
<A1,...,An>为M的形式类型参数,让<B1,...,Bn>是N的形式类型参数重命名的N的类型艾一碧的每次出现相应类型变量的范围和参数类型M和N都是一样的了.如果m2与m1具有相同的签名,或者m1的签名与m2的签名擦除相同,则方法m1的签名是方法m2的签名的子签名.
...如果m1是m2的子签名或m2是m1的子签名,则两个方法签名m1和m2是覆盖等价的.
在JSL 8#8.4.2中.Method Signature(http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2)
两个方法或构造函数M和N具有相同的签名,如果它们具有相同的名称,相同的类型参数(如果有的话)(第8.4.4节),并且在将形式参数类型N调整为类型参数之后M,相同的形式参数类型.
方法m1的签名是方法m2的签名的子签名,如果:
m2与m1具有相同的签名,或
m1的签名与m2的签名擦除相同.
如果m1是m2的子签名或m2是m1的子签名,则两个方法签名m1和m2是覆盖等价的.
简单来说,我的疑问是,从擦除方面的子签名定义我明白"没有擦除的一个签名等于来自其他签名的擦除"......而不是"擦除后的两个签名是相等的".它的微妙但重要(顺便说一句,覆盖等效定义是基于子签名定义,这就是为什么我用子签名来问)
我知道我们不能调用,instanceof List<E>因为List<E>它不是一个可再生的类型.兼顾instanceof List和instanceof List<?>工作; 然而eclipse IDE建议使用instanceof List<?>.
我想知道为什么它建议使用未绑定的通配符instanceof List<?>而不是原始调用instanceof List.未绑定的通配符是否instanceof List<?>比原始调用有任何优势instanceof List?
预先感谢.
编辑1:实际上,instanceof List与instanceof List<?>编译器在编译时将擦除类型相同.但是化妆品的原因旁边,梅纳指出的,它有其他任何理由使用instanceof List<?>赞成instanceof List?
编辑2:根据Oracle的这个条目:
- instanceof/cast表达式的类型是raw
这种情况经常发生,因为javac禁止其目标类型为泛型类型的instanceof表达式; 对于强制类型转换,编译器稍微宽松一些,因为允许转换为泛型类型,但会发出警告(参见上文).无论如何,原始类型应该由无界通配符替换,因为它们具有类似的属性和子类型.
Object o = new ArrayList<String>();List<?> list_string = (List)o;//same as (List<?>)o boolean b = o instanceof List; //same as o instanceof List<?>
因此,我们可以推断,除了Mena所说的美容理由和使用genenics的限制,instanceof List并且instanceof …
erasure ×10
generics ×10
java ×8
scala ×2
type-erasure ×2
arrays ×1
casting ×1
collections ×1
comparable ×1
gson ×1
implicit ×1
kotlin ×1
overriding ×1
reflection ×1
scala-2.10 ×1
signature ×1