-2

Hello I have two java classes "List" and "ListPlayground". The problem is i can´t override the toString() Method, because I get this Error:

error: toString() in List cannot override toString() in Object
    public String toString() {
                  ^
  return type String is not compatible with java.lang.String
  where String is a type-variable:
    String extends Object declared in class List
List.java:59: error: incompatible types: java.lang.String cannot be converted to String
        String string = "";
                        ^
  where String is a type-variable:
    String extends Object declared in class List
Note: List.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors

Here is the class I have

public class List<String> {

    private class Node {
        private String element = null;
        private Node next = null;

        private Node(String element, Node next) {
            this.element = element;
            this.next = next;
        }

        private Node(String element) {
            this.element = element;
        }
    }
    
    private Node head = null;
    private Node current = head;
    
    public void prepend(String object) {
        head = new Node(object, head);
    }
    
    public void append(String object) {
        if(head == null) {
            head = new Node(object);
            return;
        }
        Node current = head;
        while(current.next != null) {
            current = current.next;
        }
        current.next = new Node(object);
    }
    
    public String first() {
        get(0);
    }
    
    public String get(int index) {
        Node current = head;
        for(int i = 0; i < index; i++) {
            current = current.next;
        }
        return current.element;
    }
    
    public int size() {
        Node current = head;
        int size = 0;
        for(; current != null; size++) {
            current = current.next;
        }
        return size;
    }
    

    public String toString() {
        String string = "";
        while(current != null) {
            string += head.element + " -> ";
            current = head.next;
        }
        return string;
    }
}

Here is the ListPlayground class:

public class ListPlayground {

    public static void main(String[] args) {
    
        List<String> stringliste = new List()<>;
        
        stringliste.append("World");
        stringliste.append("!");
        stringliste.prepend("Hello");
        
        
        System.out.println("The Length of the List is: " + stringliste.size());
        System.out.println("The first Element of the List is: " + stringliste.first());
        System.out.println("The element with Index 2 is: " + stringliste.get(2));
        System.out.println("The last element is: " + stringliste.get(stringliste.size() - 1));
        System.out.println("The whole List is: " + stringliste.toString());
        System.out.println("And again the whole List " + stringliste.toString());
    
    }

}

can somebody help me?

I tried to debug my code but I did not succeed. I know that the class "Object" is the superclass of all classes and I have to override the toString() Method, but I do not understand why the toString() method is wrong i the List class?

Valerij
  • 7
  • 3
  • 5
    Why is your class generic in a type variable named `String`? – user2357112 Jan 15 '23 at 12:13
  • Hey I did not write the code. My task is just debugging. So I tried to debug this code and I made it generic at the beginning "public class List" – Valerij Jan 15 '23 at 12:14
  • 2
    Well, you are supposed to have a *type variable* there. Not a real type. – RealSkeptic Jan 15 '23 at 12:16
  • plus all solution there you can change your toString to be public java.lang.String toString() but if you want to create generic class you should use singe letter to your generic type like T K V S and so on also stay away from naming your class same as type from the standard api cause it would confuse you or who ever use your type if it was List for api or your own class chekc this tutorial for generic which has best practice also https://dev.java/learn/generics/ –  Jan 15 '23 at 12:40
  • ops rgnt already mentioned the java.lang.String toString() –  Jan 15 '23 at 12:42

3 Answers3

4

It's because your generic type is called String, which is shadowing the java.lang.String class. They both extend the Object, but they are fundamentally different.

  1. To fix this problem, call your generic argument something else. i.e.:
public class List<T> {

    private class Node {
        private T element = null;
        private Node next = null;

        private Node(T element, Node next) {
            this.element = element;
            this.next = next;
        }

        private Node(T element) {
            this.element = element;
        }
    }
    
    private Node head = null;
    private Node current = head;
    
    public void prepend(T object) {
        head = new Node(object, head);
    }
    
    public void append(T object) {
        if(head == null) {
            head = new Node(object);
            return;
        }
        Node current = head;
        while(current.next != null) {
            current = current.next;
        }
        current.next = new Node(object);
    }
    
    public T first() {
        get(0);
    }
    
    public T get(int index) {
        Node current = head;
        for(int i = 0; i < index; i++) {
            current = current.next;
        }
        return current.element;
    }
    
    public int size() {
        Node current = head;
        int size = 0;
        for(; current != null; size++) {
            current = current.next;
        }
        return size;
    }
    

    public String toString() {
        String string = "";
        while(current != null) {
            string += head.element + " -> ";
            current = head.next;
        }
        return string;
    }
}
  1. or you could just specify which String you want to return in the toString() method i.e.:
public java.lang.String toString() {
        java.lang.String string = "";
        while(current != null) {
            string += head.element + " -> ";
            current = head.next;
        }
        return string;
    }

Generally I would prefer solution 1) over 2). It's never a good idea to introduce a generic parameter which shadows a class name.

rgnt
  • 551
  • 2
  • 7
2

When you use public class List<String>, "String" is used as a generic type and not java.lang.String.

You should change your class declaration and remove the type as you don't need it.

public class List {
... your code here
}

public class List<T> is same as public class List<String> and in both the cases, it is generic type and not a java.lang.String type.

Pshemo
  • 122,468
  • 25
  • 185
  • 269
Froyo
  • 17,947
  • 8
  • 45
  • 73
  • The problem is if I remove the type I can´t run the program. I mean if I type "javac ListPlayground" I get the Error :ListPlayground.java:5: error: type List does not take parameters List stringliste = new List<>(); ^ ListPlayground.java:5: error: cannot infer type arguments for List List stringliste = new List<>(); ^ reason: cannot use '<>' with non-generic class List 2 errors – Valerij Jan 15 '23 at 12:25
  • @Valerij It looks like `ListPlayground` relies on fact that `List` is generic. If you change `List` to non-generic you also need to correct code which assumes that it is generic. So instead of `List stringliste = new List<>();` you should use `List stringliste = new List();`. – Pshemo Jan 15 '23 at 12:29
  • Pshemo thank you, but my tsk is to make a generic List. Sr I did not say it at the beginning – Valerij Jan 15 '23 at 12:34
  • @Valerij In that case change `public class List { .. }` to `public class List { .. }` to stop shadowing `java.lang.String` with `` type parameter. Also inside that class change most Strings to T (except when `java.lang.String` is actually needed, like in case of return type of `toString()` method). See https://stackoverflow.com/a/75125009, specifically solution (1). – Pshemo Jan 15 '23 at 12:39
  • You can also make them generic, but not as `class List` because your generic type `String` hides type `String` in `java.lang`! This is the cause of your problem! Declare your class as `class List` as usual. Then when you instantiate your class you specify the type to use. So eg. `List myList = new List<>()` –  Jan 15 '23 at 12:43
1

A List<String> class is declared in the code, which syntactically is like declaring a List<T> class where the "T" is called "String."

So when you try to do the override the compiler is like seeing this:

public T toString()

Also in the implemation of the toString method it is very inefficient to use the +=, it uses a StringBuilder instead.