在使用泛型类时, 我们可以使用一个具体的类型, 例如可以定义一个 List 的对象, 我们的泛型参数就是 Integer; 我们也可以使用通配符 ? 来表示一个未知类型, 例如 List 就表示了泛型参数是某个类型, 只不过我们并不知道它的具体类型时什么.
List所声明的就是所有类型都是可以的, 但需要注意的是, List并不等同于List
正因为类型未知, 我们就不能通过 new ArrayList() 的方法来创建一个新的ArrayList 对象, 因为编译器无法知道具体的类型是什么. 但是对于 List 中的元素, 我们却都可以使用 Object 来接收, 因为虽然类型未知, 但肯定是Object及其子类.
我们在上面提到了, List 中的元素只能使用 Object 来引用, 这样作肯定是不太方便的, 不过幸运的是, Java 的泛型机制允许我们对泛型参数的类型的上界和下界做一些限制, 例如 List 定义了泛型的上界是 Number, 即 List 中包含的元素类型是 Number 及其子类. 而 List 定义了泛型的下界, 即 List 中包含的是 Number 及其父类. 当引入了泛型参数的上界和下界后, 我们编写代码相对来说就方便了许多, 不过也引入了新的问题, 即我们在什么时候使用上界, 什么时候使用下界, 以及它们的区别和限制到底时什么? 下面我来说说我的理解.
? extends T
? extends T 描述了通配符上界, 即具体的泛型参数需要满足条件: , 例如:
List numberArray = new ArrayList(); // Number 是 Number 类型的
List numberArray = new ArrayList(); // Integer 是 Number 的子类
List numberArray = new ArrayList(); // Double 是 Number 的子类
上面三个操作都是合法的, 因为 ? extends Number 规定了泛型通配符的上界, 即我们实际上的泛型必须要是 Number 类型或者是它的子类, 而 Number, Integer, Double 显然都是 Number 的子类(类型相同的也可以, 即这里我们可以认为 Number 是 Number 的子类).
关于读取
根据上面的例子, 对于 List numberArray 对象:
我们能够从 numberArray 中读取到 Number 对象, 因为 numberArray 中包含的元素是 Number 类型或 Number 的子类型.
同理, 我们也不能从 numberArray 中读取到 Double 类型.
关于写入
根据上面的例子, 对于 List numberArray 对象:
我们不能添加 Number 到 numberArray 中, 因为 numberArray 有可能是List 类型
我们不能添加 Integer 到 numberArray 中, 因为 numberArray 有可能是 List 类型
我们不能添加 Double 到 numberArray 中, 因为 numberArray 有可能是 List 类型
即, 我们不能添加任何对象到 List 中, 因为我们不能确定一个 List 对象实际的类型是什么, 因此就不能确定插入的元素的类型是否和这个 List 匹配. List 唯一能保证的是我们从这个 list 中读取的元素一定是一个 T 类型的.
? super T
? super T 描述了通配符下界, 即具体的泛型参数需要满足条件: , 例如:
// 在这里, Integer 可以认为是 Integer 的 "父类"
List array = new ArrayList();
// Number 是 Integer 的 父类
List array = new ArrayList();
// Object 是 Integer 的 父类
List array = new ArrayList();
关于读取
对于上面的例子中的 List array 对象:
我们不能保证可以从 array 对象中读取到 Integer 类型的数据, 因为 array 可能是 List 类型的.
我们不能保证可以从 array 对象中读取到 Number 类型的数据, 因为 array 可能是 List 类型的.
Producer extends: 如果我们需要一个 List 提供类型为 T 的数据(即希望从 List 中读取 T 类型的数据), 那么我们需要使用 ? extends T, 例如 List. 但是我们不能向这个 List 添加数据.
Consumer Super: 如果我们需要一个 List 来消费 T 类型的数据(即希望将 T 类型的数据写入 List 中), 那么我们需要使用 ? super T, 例如 List. 但是这个 List 不能保证从它读取的数据的类型.
如果我们既希望读取, 也希望写入, 那么我们就必须明确地声明泛型参数的类型, 例如 List.
例子:
public class Collections {
public static void copy(List dest, List src)
{
for (int i=0; i
上面的例子是一个拷贝数据的代码, src 是 List 类型的, 因此它可以读取出 T 类型的数据(读取的数据类型是 T 或是 T 的子类, 但是我们不能确切的知道它是什么类型, 唯一能确定的是读取的类型 is instance of T), dest 是 List 类型的, 因此它可以写入 T 类型或其子类的数据.
如果希望workflow存储最近20次的log,在session里的Config Object设置,log options做配置,save session log :sessions run ;savesessio log for these runs:20
session下面的source 里面有个tracing 
今天遇到一个客户BUG,当前的jdbc连接用户是root,然后部分删除操作都会报下面这个错误:The user specified as a definer ('aaa'@'localhost') does not exist
最后找原因发现删除操作做了触发器,而触发器里面有这样一句
/*!50017 DEFINER = ''aaa@'localhost' */
原来最初
O7_DICTIONARY_ACCESSIBILITY参数控制对数据字典的访问.设置为true,如果用户被授予了如select any table等any table权限,用户即使不是dba或sysdba用户也可以访问数据字典.在9i及以上版本默认为false,8i及以前版本默认为true.如果设置为true就可能会带来安全上的一些问题.这也就为什么O7_DICTIONARY_ACCESSIBIL
#h1#
0、完成课堂例子
1、将一个四位数逆序打印
1234 ==> 4321
实现方法一:
# include <stdio.h>
int main(void)
{
int i = 1234;
int one = i%10;
int two = i / 10 % 10;
int three = i / 100 % 10;
===================================================================
第一个
===================================================================
try{
CString sql;
sql.Format("select * from p