我是Kotlin的新手.当我在地图中学习存储属性时.我尝试以下用法.
class User(val map: MutableMap<String, String>) {
val name: String by map
}
Run Code Online (Sandbox Code Playgroud)
class User(val map: MutableMap<String, in String>) {
val name: String by map
}
Run Code Online (Sandbox Code Playgroud)
class User(val map: MutableMap<String, out String>) {
val name: String by map
}
Run Code Online (Sandbox Code Playgroud)
前两个都是工作,最后一个都失败了.使用out修饰符,字节码getName如下:
public final java.lang.String getName();
0 aload_0 [this]
1 getfield kotl.User.name$delegate : java.util.Map [11]
4 astore_1
5 aload_0 [this]
6 astore_2
7 getstatic kotl.User.$$delegatedProperties : kotlin.reflect.KProperty[] [15]
10 iconst_0
11 aaload
12 astore_3 …Run Code Online (Sandbox Code Playgroud) 我有两个问题
我的书中说明了"如果没有上限指定了通配符,那么只能在通配符类型的值上调用Object类型的方法"
我不知道这可能是什么意思.这是什么意思?
对于外卡类型(无界和有界)有什么限制?例如,如果我有一个引用MyClass<?>或者MyClass<? extends SomeOtherClass>,我不允许通过该引用调用哪些方法.我不明白外卡允许或禁止我做什么,这可能是我不理解书中引用的原因.
我有第二部分的例子:
class SomeOtherClass
{
[...]
}
class MyClass<T>
{
[...]
}
class Test
{
public static void main(String[] arg)
{
MyClass<? extends SomeOtherClass> myClass = new MyClass<String>() // for instance what does the wild card reference limit me to in any way. In a general sence.
}
}
Run Code Online (Sandbox Code Playgroud) 我得到"类型不匹配:无法转换List<CherryCoke>为List<Coke<?>>"
看起来像'樱桃可乐列表'不是'可乐列表'.这是违反直觉的.我怎么能创建'xs',如果它必须是a List<Coke<?>>并且我必须有一个子类Coke<Cherry>?
class Taste { }
class Cherry extends Taste { }
abstract class Coke<T extends Taste> { }
class CherryCoke extends Coke<Cherry> { }
class x {
void drink() {
List<Coke<?>> xs = Arrays.asList(new CherryCoke());
}
}
Run Code Online (Sandbox Code Playgroud) 我正在使用来自第三方库(Reflection)的方法,该方法应该找到给定类型的子类型并且看起来像
public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
...
Run Code Online (Sandbox Code Playgroud)
当调用者代码看起来像
Class<?> type = ...
Set<Class<?>> subTypes = reflections.getSubTypesOf(type);
Run Code Online (Sandbox Code Playgroud)
我收到编译错误:" cannot convert from Set<Class<? extends capture#19-of ?>> to Set<Class<?>>".以下修复了这种情况:
Class<?> type = ...
Set<?> subTypes = reflections.getSubTypesOf(ht);
Run Code Online (Sandbox Code Playgroud)
所以看起来不正确的唯一可能的补救措施Set<Class<? extends ?>>是Set<?>,但不是Set<Class<?>>.为什么会这样?谢谢你对此有任何解释.
我正在读关于函数式编程的讨论,我有一个非常基本的问题:
如果我在Java中有两个函数
int add(int x, int y){
return x+y;
}
Run Code Online (Sandbox Code Playgroud)
我创建了另一种方法
int increment(int y){
return add(1, y);
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,当我写increment函数时,我实际上是在做咖喱add吗?
在下面的代码Java中,我创建了一个列表nums.我可以在声明期间分配另一个列表.但是除了null.之外不能添加新项目.那么,这是否意味着nums只读?为什么?是否可以在该列表中添加新项目?
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); //Generates error
nums.addAll(ints); //Generates error
nums.add(null); //works
System.out.println(nums.get(0)); //works
Run Code Online (Sandbox Code Playgroud)
我已经通过了这个链接.我无法得到确切的理由.
我想创建一个迭代器类,它允许我遍历具有泛型类型(例如lst1 integer,lst2 string)的列表.为此,我必须考虑以下给定的情况.
该接口是通用迭代器.这部分代码无法修改.
interface Iterator<E> {
E next ();
boolean hasNext();
}
Run Code Online (Sandbox Code Playgroud)
列表类也定义如下.最重要的是,列表对象可以使用方法getIterator()返回迭代器对象.这部分代码无法修改.
class List<T> {
class ListNode {
T val;
ListNode next;
ListNode (T v) {
val = v; next = null;
}
}
ListNode head;
List (ListNode hd) { head = hd; }
List () { this(null); }
void prepend (T val) {
ListNode p = new ListNode(val);
p.next = head;
head = p;
}
//some other methods
class ListIterator implements Iterator<T> {
ListNode pos;
ListIterator () …Run Code Online (Sandbox Code Playgroud) 用语言来解释很难,但是Java Generics给了我一个意想不到的结果.我希望如果我说列表是类型? extends Object,我可以在那里存储任何东西.因此,如果是类型列表Wrapper<? extends Object>,我可以在那里存储任何类型的Wrapper.等等.这对我来说很有意义.但我们假设我们有:
private static class Wrapper<T> {
public Wrapper(T t) { /**/ }
}
Run Code Online (Sandbox Code Playgroud)
我想要的东西是这样的:
private static final List<Wrapper<Wrapper<? extends Object>>> ls1 = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)
请注意,这给了我一个错误:
public static <T> doit(T t) {
Wrapper<Wrapper<T>> l1 = new Wrapper<>(new Wrapper<>(t));
ls1.add(l1); // nok
// add (Wrapper<Wrapper<? extends java.lang.Object>>) in List
// cannot be applied to (Wrapper<Wrapper<T>>
}
Run Code Online (Sandbox Code Playgroud)
但是如果我将Wrapper包装在辅助包装器(rs)中,那么:
private static class C<T> extends Wrapper<Wrapper<T>> {
public C(T t) {
super(new Wrapper<>(t));
}
}
private …Run Code Online (Sandbox Code Playgroud) 我想创建一个IdentityHashMap<Class<T>, Consumer<T>>.基本上,我想用一种方法来映射一个类型,说明如何处理这种类型.
我想动态地能够用对象X说,执行Y.我能做到
private IdentityHashMap<Class<?>, Consumer<?>> interceptor = new IdentityHashMap<>();
Run Code Online (Sandbox Code Playgroud)
但它很糟糕,因为我在使用它时必须在lamba中投射对象.
例:
interceptor.put(Train.class, train -> {
System.out.println(((Train)train).getSpeed());
});
Run Code Online (Sandbox Code Playgroud)
我想做的是
private <T> IdentityHashMap<Class<T>, Consumer<T>> interceptor = new IdentityHashMap<>();
Run Code Online (Sandbox Code Playgroud)
但似乎不允许这样做.有没有办法做到这一点 ?使用此类型的方法映射类型的最佳解决方法是什么?
在阅读 Kotlin 泛型类型变化和投影时,我想到了一个完全陌生的概念。有人可以解释一下作者想要解释的想法是什么吗?请引用来自Kotlin in Action, MEAP 的引用:
获得out已经有out变化的类型参数的投影是没有意义的,例如List<out T>。这意味着与 相同List<T>,因为List被声明为class List<out T>。Kotlin 编译器会警告这样的投影是多余的。
这里有两个具体问题:
java ×9
generics ×8
kotlin ×2
delegates ×1
dictionary ×1
generic-list ×1
iterator ×1
java-8 ×1
jvm ×1
list ×1
null ×1
type-safety ×1
wildcard ×1