0

I'm studying about java generic classes. Create one generic class with T as type parameter.

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);
    }
}

In above example, the type of T could string, integer or any other type. But is that possible I could create generic class with specific type argument. Like below example, but its showing error "Cannot make a static reference to the non-static type String"

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.
    }

Can anyone tell me, Is that possible to create generic class with String as parameter Class generictype ? If not, then why ?

Ele
  • 33,468
  • 7
  • 37
  • 75
linuxman
  • 51
  • 8
  • @AndyTurner, Can you share one example how can I achieve in my second example ? – linuxman Jan 07 '18 at 13:15
  • "is that possible I could create generic class with specific type argument" is unclear, if it is generic then it is not specific. When you type `public class Genericstring {...}` you are still creating generic type, but its name is String, which *hides* `java.lang.String` in scope of that class. Proper solution depends on what you actually want to do. You can get rid of generics and just use String in places you want, or you could create another class which will `extend Genericstring{...}`. For now your question looks like [X/Y problem](https://meta.stackexchange.com/q/66377) – Pshemo Jan 07 '18 at 13:18

2 Answers2

2

Genericstring<String> is declaring a type variable called String.

This makes all other uses of String refer to that type variable, not java.lang.String. Where you've got the argument to main declared as String[], it thinks you mean the type variable. And because this is a static method, you can't refer to that type parameter there, because it belongs to instances of the class.

But is that possible I could create generic class with specific type argument.

What you're describing is a non-generic class. Remove the type parameter.

public class Genericstring {
  String name;

  // Etc
}
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

No, you can't.

This code: Genericstring<String> is only naming the Generic Type Variable rather than setting as java.lang.String.

The most you can do is declaring a generic type that extends a specific Class:

public class Genericstring<T extends String>

Example:

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
    }
}

UPDATED: According to the comments, my answer has generated a lot of confusion because the way I've implemented.

@linuxman this is not the only way to accomplish your scenario and your right when you're mentioning Cant we mention like only B or B<T extends String>?:

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 is right:

In this scenario only type available for is String itself, but if it is only one type then there is no point in having a generic type because it main purse is to allow us to use our class with many types.

Also, about your doubt regarding final classes:

Reference: https://stackoverflow.com/a/5181618/1715121

A final class is simply a class that can't be extended.

(This does not mean that all references to objects of the class would act as if they were declared as final.)

When it's useful to declare a class as final is covered in the answers of this question:

If Java is object oriented, and you declare a class final, doesn't it stop the idea of class having the characteristics of objects?

In some sense yes.

By marking a class as final you disable a powerful and flexible feature of the language for that part of the code. Some classes however, should not (and in certain cases can not) be designed to take subclassing into account in a good way. In these cases it makes sense to mark the class as final, even though it limits OOP. (Remember however that a final class can still extend another non-final class.)

Related article: Java: When to create a final class


@linuxman What you're trying to accomplish doesn't make sense because the purpose of a Generic Type is to declare contracts that could implement a behavior with different types.

Hope it helps and clears your doubts.

Community
  • 1
  • 1
Ele
  • 33,468
  • 7
  • 37
  • 75
  • but its shows warning "The type parameter T should not be bounded by the final type String. Final types cannot be further extended" Why ? – linuxman Jan 07 '18 at 15:35
  • 1
    @linuxman Because "Final types cannot be further extended" so there is no `class SomeClass extends String{..}` because `String` class was declared as `final` which explicitly prevents extending it. In this scenario only type available for `` is String itself, but if it is only one type then there is no point in having generic type because it main purse is to allow us to use our class with *many* types. – Pshemo Jan 07 '18 at 15:45
  • @Eleazar, So you mean when something is final, and if any subject extends that, then that subject lost his identity completely like in this case ? Cant we create of type who extended that ? Secondly In class C, why we did mention like C extends B ? Cant we mention like only B or B ? I'm confuse here, what's the purpose by defining that way only ? – linuxman Jan 07 '18 at 16:22
  • @linuxman the keyword `final` *prevents* from extending, so `class A extends String{...}` will throw a compiler error – Lino Jan 07 '18 at 16:28
  • 1
    @linuxman `final` has few meanings depending on context. If you make variable final it means you can only assign its value once like `final double PI = 3.14;`. If you make method final like `final void someMethod(){...}` it means that you forbid overriding it in subclass. If you make entire class final like `final class A{...}` then you forbid extending that class (if you will try to compile `class B extends A{..}` you will get compilation error because `A` is final). So since String is final `` is useless because it describes only one class which defeats purpose of generics. – Pshemo Jan 07 '18 at 16:41
  • @Pshemo, if you will try to compile class B extends A{..} you will get compilation error because A is final then why not T extends String> gives compile time error ? – linuxman Jan 07 '18 at 16:50
  • @linuxman Because while it is pointless it still valid syntax (it doesn't break any language rules) so compiler is not *preventing* you from doing it, but gives you *warning* about it. But it is good practice to treat any warnings like they ware compilation errors. You can even set up your IDE to not compile code with warnings. – Pshemo Jan 07 '18 at 16:56
  • @@Pshemo, Why its valid and not break any language rules ? Like you said in your previous comment its fact that final cant be extended. In other cases you have mentioned it shows directly error while writing code but in this case why its warning only ? Its extending final, so has to be error.Isnt it ? – linuxman Jan 07 '18 at 16:59
  • 1
    @linuxman It doesn't break any language rule because `` still has some type which is *valid* for `T` and that type is String itself. So if for some strange reason (maybe for unusual testing) you decide to let T accept only String compiler will let you do it, but will warn you that this may not be what you wanted (since generics shouldn't be used that way). Compiler should prevent us from doing things which are obviously dangerous/incorrect, but warnings are used for things which *may not be* what programmer wanted, while still being valid code. – Pshemo Jan 07 '18 at 17:11
  • @Pshemo, Last question please, you said " still has some type which is valid for T and that type is String itself". Can you tell me in code mentioned by Eleazar, where it gets proved that T has a String type ? The moment we assign the value in class C ? or some where else ? – linuxman Jan 07 '18 at 17:23
  • 1
    @linuxman "where it gets proved that T has a String type" if I understand you correctly you are asking where we set specific type for T. If that is the case then it happens at `C extends B{..}`. If `B` wouldn't be abstract we would be able to also write code like `B b = new B()` (but `abstract` makes it impossible). For now all I can say is that you should probably read Java tutorial/book ("Head First Java" was nice, also Thinking in Java is very detailed). – Pshemo Jan 07 '18 at 17:33
  • @linuxman I've updated my answer explaining a little more your scenario. – Ele Jan 07 '18 at 19:48