我认为参数和通配符占位符大致具有相同的含义,其中第一个用于定义类和方法,第二个用于声明变量。但显然事实并非如此。
import java.util.List;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Consumer<List<? extends Number>> l1 = null;
Consumer<List<? extends Number>> l2 = null;
l1 = l2; // compiles
}
static <T extends Number> void m(Consumer<List<T>> l) {
Consumer<List<? extends Number>> l3 = l; // doesn't compile
}
}
我认为该行Consumer<List<? extends Number>> l3 = l
应该与l1 = l2;
一样。但事实并非如此。有人可以解释为什么这个样本不能编译,我该如何解决这个问题。
答案 0 :(得分:0)
Consumer<List<T>>
不是Consumer<List<? extends Number>>
的子类型,即使List<T>
是List<? extends Number>
的子类型,就像Foo<Dog>
不是子类型Foo<Animal>
一样Dog
即使Animal
是Consumer<? extends List<? extends Number>> l3 = l;
的子类型。
通用类型参数是不变的,这意味着(除非您在顶层有通配符),它们必须与完全匹配。如果您希望它与不同的类型参数兼容,您必须在顶层有一个通配符,如下所示:
static void m(Consumer<? extends List<? extends Number>> l3)
或者您可以将方法声明为
Consumer
它将接受之前接受的所有论据。
(但是,我想指出,使用T
声明的方法实际上没有任何意义。您的方法在List<T>
上是通用的,并且它接收消费者的内容List<T>
。您的方法几乎没有办法使用此消费者,因为您的方法必须将T
传递给它,但您的方法不知道T
是什么,并且它没有T
类型的其他参数或任何其他方式来确定List<T>
是什么或得到<?php
$servername = "localhost";
$username = "myusername";
$password = "mypassword";
$dbname = "mydb";
// Create connection
/* was $conn */
$mysqli = new mysqli($servername, $username, $password, $dbname);
// Check connection
// change $conn tp $mysqli
if ($mysqli->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$mysqli->set_charset("utf8");
if (isset($_REQUEST['q'])){
$target= $_REQUEST['q'];
$sql = " SELECT *
FROM TABLE1
WHERE name
LIKE '%$target%'";
$result = $mysqli->query($sql)
or die($mysqli->error . "<pre>$sql</pre>");
while ($row = $result->fetch_assoc()){
echo $row["number"] . " " . $row["name"]. " " . $row["hp"] . "<br>";
}
}
else {
echo "0 results";
}
?>
,所以它唯一可以安全传入的是一个空列表。所以您的方法可以使用此使用者的唯一方法是将其传递给空列表,这可能不是很有用。)