我认为你不能将Java泛型类型参数绑定到下限(即使用super关键字).我正在阅读Angelika Langer Generics常见问题解答中有关该主题的内容.他们说这基本上归结为下限无用("没有任何意义").
我不相信.我可以想象它们的用途可以帮助您更灵活地生成类型化结果的库方法的调用者.想象一个方法,它创建一个用户指定大小的数组列表,并用空字符串填充它.一个简单的声明就是
public static ArrayList<String> createArrayListFullOfEmptyStrings(int i);
Run Code Online (Sandbox Code Playgroud)
但这对您的客户来说是不必要的限制.为什么他们不能像这样调用你的方法:
//should compile
List<Object> l1 = createArrayListFullOfEmptyStrings(5);
List<CharSequence> l2 = createArrayListFullOfEmptyStrings(5);
List<String> l3 = createArrayListFullOfEmptyStrings(5);
//shouldn't compile
List<Integer> l4 = createArrayListFullOfEmptyStrings(5);
Run Code Online (Sandbox Code Playgroud)
在这一点上,我很想尝试以下定义:
public static <T super String> List<T> createArrayListFullOfEmptyStrings(int size) {
List<T> list = new ArrayList<T>(size);
for(int i = 0; i < size; i++) {
list.add("");
}
return list;
}
Run Code Online (Sandbox Code Playgroud)
但它不会编译; super在这种情况下,关键字是非法的.
上面我的例子是一个坏例子(忽略我在下面说的)?为什么这里没有下限?如果它有用,那么Java中不允许它的真正原因是什么?
我知道一个更好的组织可能是这样的:
public static void populateListWithEmptyStrings(List<? super String> list, int size); …Run Code Online (Sandbox Code Playgroud) 当增强的for循环(foreach循环)被添加到Java时,它可以使用数组或目标Iterable.
for ( T item : /*T[] or Iterable<? extends T>*/ ) {
//use item
}
Run Code Online (Sandbox Code Playgroud)
这对于仅实现一种迭代类型的Collection类非常有用,因此只有一个iterator()方法.
但是我发现自己非常沮丧地想要使用Collection类中的非标准迭代器.例如,我最近试图帮助某人使用a Deque作为LIFO /堆栈,然后按FIFO顺序打印元素.我被迫这样做:
for (Iterator<T> it = myDeque.descendingIterator(); it.hasNext(); ) {
T item = it.next();
//use item
}
Run Code Online (Sandbox Code Playgroud)
我失去了for-each循环的优点.这不仅仅是击键.如果我不需要,我不喜欢暴露迭代器,因为很容易犯it.next()两次调用等错误.
理想情况下,我认为for-each循环应该也接受了Iterator.但事实并非如此.那么在这些情况下是否存在使用for-each循环的惯用方法?我也很想听到使用像Guava这样的常见集合库的建议.
我能想出的最好的帮助方法/类是:
for ( T item : new Iterable<T>() { public Iterator<T> iterator() { return myDeque.descendingIterator(); } } ) {
//use item
}
Run Code Online (Sandbox Code Playgroud)
哪个不值得使用.
我很想看到番石榴有类似的东西Iterables.wrap,但没有找到类似的东西.显然,我可以通过类或辅助方法滚动我自己的Iterator包装器.还有其他想法吗?
编辑:作为旁注,任何人都可以给出一个有效的理由,说明为什么增强的for循环不应该只接受一个Iterator?让我使用当前的设计可能会有很长的路要走.
我帮助维护和构建一个相当大的Swing GUI,有很多复杂的交互.我经常发现自己修复了由于某些其他竞争条件导致事情进入奇怪状态的错误.
随着代码库变大,我发现通过文档指定哪些方法具有线程限制已经不那么一致了:最常见的是必须在Swing EDT上运行的方法.类似地,知道并提供静态感知将是有用的,其中(我们的自定义)侦听器通过规范在EDT上被通知.
因此,我认为这应该可以使用注释轻松实施.请注意,至少存在一个静态分析工具CheckThread,它使用注释来完成此任务.它似乎允许你声明一个方法被限制在一个特定的线程(最常见的是EDT),并将标记尝试调用该方法的方法,而不会将自己声明为局限于该线程.
所以从表面上看,这似乎是对源和构建周期的低痛苦,巨大收益.我的问题是:
我知道它是否适合我们取决于我们的情况.但是我从来没有听说过人们在实践中使用过这样的东西,说实话,它似乎并没有从一些普通的浏览中获得太多.所以我想知道为什么.
让我们假设每个线程正在进行一些FP计算,我感兴趣
我的问题:如何设计测试程序来获取这些数据?
给定一些类SomeBaseClass,这两个方法声明是否等效?
public <T extends SomeBaseClass> void myMethod(Class<T> clz)
Run Code Online (Sandbox Code Playgroud)
和
public void myMethod(Class<? extends SomeBaseClass> clz)
Run Code Online (Sandbox Code Playgroud) 我一直认为以下应该有效.我得到一个对象,我知道是Class<X>哪里X扩展一些类Xyz.为了使其类型安全,我想在下面的方法中使用Class.asSubclass:
private Class<? extends Xyz> castToXyzClass(Object o) {
final Class<?> resultClass = (Class<?>) o;
final Class<? extends Xyz> result = Xyz.class.asSubclass(resultClass);
return result;
}
Run Code Online (Sandbox Code Playgroud)
但是,在Eclipse中它不起作用,我看到的唯一解决方案是未经检查的强制转换.我敢打赌上面的代码必须工作,我已经使用过这样的东西......不知道这里有什么问题.
好的,我正在调用一个带签名的方法,(Class<? extends Throwable>... exceptions)我在main方法中得到一个"File.java使用未经检查或不安全的操作"警告:
public class VarargsFun {
public void onException(Class<? extends Throwable>... exceptions) { }
public static void main(String[] args) {
new VarargsFun().onException(IllegalArgumentException.class);
}
}
Run Code Online (Sandbox Code Playgroud)
编译器是否应该能够看到IllegalArgumentException确实扩展了RuntimeException,Exception并且Throwable?
我应该如何正确修改我的代码以摆脱这个警告?
我真的不想实例化我的例外......使用它似乎更好 .class
(不要用@SuppressWarnings任何一个!)
我正在使用java 7.感谢任何提示.
java generics exception variadic-functions compiler-warnings
是否有任何工具可以警告我不要使用以下类型的代码:
if ( someClass.equals( someString ))
Run Code Online (Sandbox Code Playgroud)
例如:
if ( myObject.getClass().equals( myClassName ))
Run Code Online (Sandbox Code Playgroud)
这样的事情是合法的Java(equals接受一个Object)但永远不会评估为true(一个类永远不能等于一个String)所以几乎肯定是一个bug.
我检查过Eclipse,FindBugs和PMD,但似乎没有人支持这个功能?
我的maven项目包括
186 <dependency>
187 <groupId>org.hamcrest</groupId>
188 <artifactId>hamcrest-all</artifactId>
189 <version>1.3</version>
190 </dependency>
Run Code Online (Sandbox Code Playgroud)
当我打字assertThat..
我希望IDEA能够确定需要以下内容
import static org.hamcrest.MatcherAssert.assertThat;
Run Code Online (Sandbox Code Playgroud)
相反,我得到了这个.

怎么能纠正?如何让IDEA执行静态导入?
我有一个基于maven的GWT项目,其中包括番石榴.我遇到麻烦,Maven尝试(并且失败)编译它找到的源guava-gwt*.jar:
could not parse error message: symbol: static setCountImpl
location: class
/home/mark/.m2/repository/com/google/guava/guava-gwt/11.0.1/guava-gwt-11.0.1.jar(com/google/common/collect/AbstractMultiset.java):100: error: cannot find symbol
return setCountImpl(this, element, count);
^
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么Maven认为需要编译源代码guava-gwt.这是我的项目的样子:
??? pom.xml
??? src
??? main
? ??? java
??? test
??? java
??? SomeTestFile.java
Run Code Online (Sandbox Code Playgroud)
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.junit.Test;
public class SomeTestFile {
@Test
public void testMethod() {
Multimap<Integer, String> someMap = ArrayListMultimap.create();
someMap.put(5, "five");
System.out.println(someMap);
}
}
Run Code Online (Sandbox Code Playgroud)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>guava-problem</groupId>
<artifactId>guava-problem</artifactId>
<version>1.0</version> …Run Code Online (Sandbox Code Playgroud)