泛型中的自限定

你的名字 2022-05-30 07:16 236阅读 0赞

自限定顾名思义就是自己限定自己,但是具体是1.怎么限定,2.限定什么,我们先看下面的代码:

  1. class Other {}
  2. class BasicOther extends BasicHolder<Other> {}
  3. public class Unconstrained {
  4. @SuppressWarnings("unused")
  5. public static void main(String[] args)
  6. {
  7. BasicOther b = new BasicOther();
  8. BasicOther b2 = new BasicOther();
  9. b.set(new Other());
  10. Other other = b.get();
  11. b.f();
  12. }
  13. }

从上面的代码可以看出,BasicOther类通过继承了将Other作为其泛型参数的BasicHoler从而可以将Other类作为.set()的参数和.get()的返回类型,下面再来看一段代码:

  1. class SelfBounded<T extends SelfBounded<T>>
  2. {
  3. T element;
  4. SelfBounded<T> set(T arg)
  5. {
  6. element = arg;
  7. return this;
  8. }
  9. T get() { return element;}
  10. }
  11. class A extends SelfBounded<A>{}
  12. class B extends SelfBounded<A>{}
  13. class C extends SelfBounded<C>
  14. {
  15. C setAndGet(C arg)
  16. {
  17. set(arg);
  18. return get();
  19. }
  20. }
  21. public class SelfBounding {
  22. public static void main(String[] args)
  23. {
  24. A a = new A();
  25. a.set(new A());
  26. a = a.set(new A()).get();
  27. a = a.get();
  28. //在a中泛型参数的类型就是A
  29. C c = new C();
  30. c = c.setAndGet(new C());
  31. //在C类的setAndGet方法中调用了基类的set方法,这个时候泛型的类型限定就起了作用
  32. }
  33. }

按照上面三种方法进行子类的创建都是可行的,最主要是要满足基类(SelfBounded)中泛型参数的要求>。显然下面的代码就不符合这样的要求:

  1. class D {}
  2. class E extends SelfBounded<D> {}

上面这样是不行的因为SelfBounded是需要一个有边界类作为参数,而不是一个原始类。下面的:

  1. class F extends SelfBounded {};

直接继承了原型的SelfBounded,直接忽略了泛型,也是会产生警告的,但是可以产生编译,也就是说自限定并不是强制的。
简单的总结一下自限定的意义就是:强制将正在定义的类当作参数传递给基类。
下面用一段代码证明自限定的并不是强制执行的:

  1. class NoSelfBounded<T>
  2. //注意这个地方所用的泛型参数并不是自限定了
  3. {
  4. T element;
  5. NoSelfBounded<T> set(T arg)
  6. {
  7. element = arg;
  8. return this;
  9. }
  10. T get()
  11. {
  12. return element;
  13. }
  14. }
  15. class A2 extends NoSelfBounded<A2>{}
  16. class B2 extends NoSelfBounded<A2>{}
  17. class C2 extends NoSelfBounded<C2>
  18. {
  19. C2 setAndGet(C2 arg)
  20. {
  21. set(arg);
  22. return get();
  23. }
  24. }

没有使用自限定的代码和之前的比起来大同小异,但是下面的代码就不一样了:

  1. class D2{}
  2. class E2 extends NoSelfBounded<D2>{}

现在使用原始类型作为泛型参数也是可行的了。

最后说一说自限定用于方法的情况

直接上代码:

  1. class SelfBounded<T extends SelfBounded<T>>
  2. {
  3. T element;
  4. SelfBounded<T> set(T arg)
  5. {
  6. element = arg;
  7. return this;
  8. }
  9. T get() { return element;}
  10. }
  11. class A extends SelfBounded<A>{}
  12. class SelfBoudingMethods
  13. {
  14. static <T extends SelfBounded<T>> T f(T arg)
  15. {
  16. return arg.set(arg).get();
  17. }
  18. public static void main(String[] args)
  19. {
  20. A a = f(new A());
  21. }
  22. }

简单来说就是将自限定的语法用在方法参数上,但是与自限定类不同的是,下面的代码将会出现错误:

  1. class SelfBounded<T extends SelfBounded<T>>
  2. {
  3. T element;
  4. SelfBounded<T> set(T arg)
  5. {
  6. element = arg;
  7. return this;
  8. }
  9. T get() { return element;}
  10. }
  11. class A extends SelfBounded<A>{}
  12. class B extends SelfBounded<A>{}
  13. class SelfBoudingMethods
  14. {
  15. static <T extends SelfBounded<T>> T f(T arg)
  16. {
  17. return arg.set(arg).get();
  18. }
  19. public static void main(String[] args)
  20. {
  21. B a = f(new B());
  22. //上面一行的代码将导致无法编译
  23. }
  24. }

此时对B的自限定和类的继承不同,之前类的继承时

  1. class A2 extends NoSelfBounded<A2>{}
  2. class B2 extends NoSelfBounded<A2>{}

仅仅是类与类之间的继承,并不存在参数的检查。
最后总结一下:自限定,通过>的方式进行限定,用来限制参数。

发表评论

表情:
评论列表 (有 0 条评论,236人围观)

还没有评论,来说两句吧...

相关阅读