【问题标题】:java generic classes of String non primitive typeString非原始类型的java泛型类
【发布时间】:2018-01-07 13:08:40
【问题描述】:

我正在研究 java 泛型类。创建一个以 T 作为类型参数的泛型类。

public class Genericstring<T> {
    String name;

    public void set(String name){
        this.name = name;
    }

    public static void main(String[] args){
        Genericstring<String> o = new Genericstring<String>();
        o.set("Generic");

        System.out.println(o.name);
    }
}

在上面的例子中,T 的类型可以是字符串、整数或任何其他类型。但是有可能我可以创建具有特定类型参数的泛型类。像下面的例子,但它显示错误“无法对非静态类型字符串进行静态引用”

public class Genericstring<String> {
    String name;

    public static void main(String[] args){     
        //Here creating object always having string type attributes. No need to specify like did in above example.
    }

谁能告诉我,是否可以使用 String 作为参数创建泛型类 Class generictype ?如果不是,那为什么?

【问题讨论】:

  • @AndyTurner,你能分享一个例子,我如何在第二个例子中实现?
  • “是否有可能我可以创建具有特定类型参数的泛型类”尚不清楚,如果它是泛型的,那么它不是特定的。当您键入public class Genericstring&lt;String&gt; {...} 时,您仍在创建泛型类型,但它的名称是String,它隐藏 java.lang.String 在该类的范围内。正确的解决方案取决于您实际想要做什么。您可以摆脱泛型,只在您想要的地方使用 String,或者您可以创建另一个将 extend Genericstring&lt;String&gt;{...} 的类。现在你的问题看起来像X/Y problem

标签: java generics


【解决方案1】:

Genericstring&lt;String&gt; 正在声明一个名为 String 的类型变量。

这使得String 的所有其他用途都指向该类型变量,而不是java.lang.String。如果您将main 的参数声明为String[],它认为您的意思是类型变量。而且因为这是一个静态方法,你不能在那里引用那个类型参数,因为它属于类的实例。

但是我是否可以创建具有特定类型参数的泛型类。

您所描述的是一个非泛型类。移除类型参数。

public class Genericstring {
  String name;

  // Etc
}

【讨论】:

    【解决方案2】:

    不,你不能。

    此代码:Genericstring&lt;String&gt; 仅命名通用类型变量,而不是设置为 java.lang.String。

    你能做的最多就是声明一个扩展特定类的泛型类型:

    public class Genericstring<T extends String>
    

    示例:

    abstract class B<T extends String> {
        protected T value;
        
        public T getValue() {
            return value;   
        }
    
        public void handleValue() {
            System.out.println(this.getValue().substring(0, 5));
        }
    }
    
    class C extends B<String>{
        public C() {
            this.value = "Hello World";
        }
    }
    
    public class A {
        public static void main(String[] args) {
            C obj = new C();
            obj.handleValue(); // prints Hello
        }
    }
    

    更新:根据 cmets 的说法,我的回答引起了很多混乱,因为我实施的方式。

    @linuxman这不是完成你的场景和你提到的权利的唯一方法我们不能只提到B or B&lt;T extends String&gt;吗?

    class B<T extends String> {
        protected T value;
    
        public T getValue() {
            return value;
        }
    
        public void handleValue() {
            System.out.println(this.getValue().substring(0, 5));
        }
    }
    
    public class A {
        public static void main(String[] args) {
            B obj = new B<String>();
            obj.handleValue();
        }
    }
    

    @Pshemo 是对的:

    在这种情况下,唯一可用的类型是 String 本身,但如果它只有一种类型,那么拥有泛型类型就没有意义,因为它的主要目的是允许我们使用具有多种类型的类。

    另外,关于您对期末课程的疑问:

    参考:https://stackoverflow.com/a/5181618/1715121

    final 类只是一个无法扩展的类。

    (这并不意味着对类对象的所有引用都会像声明为final一样。)

    这个问题的答案涵盖了将类声明为 final 是否有用:

    如果Java是面向对象的,你声明了一个类final,是不是就打消了类具有对象特性的想法?

    在某种意义上是的。

    通过将类标记为最终类,您会禁用该部分代码的强大而灵活的语言功能。然而,一些类不应该(在某些情况下不能)被设计为以一种好的方式考虑子类化。在这些情况下,将类标记为 final 是有意义的,即使它限制了 OOP。 (但请记住,最终类仍然可以扩展另一个非最终类。)

    相关文章:Java: When to create a final class


    @linuxman 你试图完成的事情没有意义,因为通用类型的目的是声明可以实现不同类型行为的合约。

    希望它能帮助您消除疑虑。

    【讨论】:

    • 但它显示警告“类型参数 T 不应受最终类型 String 的限制。最终类型不能进一步扩展”为什么?
    • @linuxman 因为“最终类型不能进一步扩展”所以没有class SomeClass extends String{..} 因为String 类被声明为final,它明确禁止扩展它。在这种情况下,&lt;T extends String&gt; 唯一可用的类型是 String 本身,但如果它只是一种类型,那么使用泛型类型就没有意义,因为它的主要目的是允许我们将我们的类与 many一起使用> 类型。
    • @linuxman final 根据上下文的不同含义很少。如果您将变量设为 final,则意味着您只能像 final double PI = 3.14; 一样为其赋值一次。如果你像final void someMethod(){...} 这样将方法设为final,这意味着你禁止在子类中覆盖它。如果你像final class A{...} 一样使整个类成为final,那么你禁止扩展该类(如果你试图编译class B extends A{..},你会得到编译错误,因为A 是final)。因此,由于 String 是最终的,&lt;T extends String&gt; 是无用的,因为它只描述了一个违背泛型目的的类。
    • @linuxman 它并没有破坏任何语言规则,因为&lt;T extends String&gt; 仍然有一些类型是 valid 对于T 并且该类型是 String 本身。所以如果出于某种奇怪的原因(可能是为了不寻常的测试)你决定让 T 只接受 String 编译器会让你这样做,但会警告你这可能不是你想要的(因为不应该那样使用泛型) .编译器应该阻止我们做明显危险/不正确的事情,但警告用于可能不是程序员想要的事情,同时仍然是有效的代码。
    • @linuxman “证明 T 有一个字符串类型”如果我理解正确你是问我们在哪里为 T 设置特定类型。如果是这种情况,那么它发生在 C extends B&lt;String&gt;{..} .如果B 不是抽象的,我们也可以编写像B&lt;String&gt; b = new B&lt;String&gt;() 这样的代码(但abstract 使它不可能)。现在我只能说你应该阅读 Java 教程/书(“Head First Java”很好,Java 中的思考也很详细)。
    猜你喜欢
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 2012-04-03
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多