1

Trying to wrap stream elements with my class Establishment, but it can't infer ouput type of constructor, thinking it is a stream of objects:

enter image description here

java: cannot find symbol
  symbol:   method getEstablishment()
  location: class java.lang.Object

Why and how to fix?

Can't specify type in any way

return q.getResultStream().<Establishment>map(Establishment::new).findFirst().orElse(new Establishment()).getEstablishment();

is it still possible?

Dims
  • 47,675
  • 117
  • 331
  • 600
  • 4
    Does `g.getResultStream()` return a raw `Stream` (without generic parameters)? – Denis Zavedeev Feb 23 '21 at 15:39
  • 1
    What does `q.getResultStream()` return, what kind of constructor does `Establishment` have (and why does a class named `Establishment` have a method named `getEstablishment()`)? – Kayaman Feb 23 '21 at 15:56

1 Answers1

3

It seems, there are raw types somewhere:

To create a parameterized type of Box, you supply an actual type argument for the formal type parameter T:

Box<Integer> intBox = new Box<>();

If the actual type argument is omitted, you create a raw type of Box:

Box rawBox = new Box();

It might be that in your code:

  • q.getResultStream() returns a raw Stream.

    The method could look similar to:

    public Stream getResultStream() {
        return Stream.of();
    }
    
  • Return type of getResultStream is not raw, but the type of q is raw itself. E.g.:

    public class Page<T> {
        public Stream<T> stream() {
            return Stream.of();
        }
    }
    
    public class Main {
        public static void test(Page q) {
            //                  ^^^^ raw type
            q.stream();
        }
    }
    

Despite the cause, the problem is: when raw types are used one loses:

the ability to use generics in any way for instance members

So any further usage of the stream returns raw Stream. The methods of Establishment become "invisible" and compilation fails.

Possible fixes:

  1. Explicit cast introduction:

    Establishment establishment = ((Stream<?>) q.getResultStream())
            .map(Establishment::new)
            .findFirst()
            .orElseGet(Establishment::new);
    
    • The Stream is cast to a Stream<?> which is an unbounded wildcard type
    • The Function in the map method can be viewed as a function accepting an Object and returning a T (Establsihment)
  2. Raw types elimination

    • Raw types are used for backward compatibility
    • They are barely present in the modern source code (Generics were introduced in Java 5, which came out in 2004)
    • It is highly recommended to avoid them

Can't specify type in any way

 return q.getResultStream()
   .<Establishment>map(Establishment::new)
   .findFirst()
   .orElse(new Establishment())
   .getEstablishment();

is it still possible?

Please note, that Intellij IDEA might be a little bit misleading there.

Here is a minimal example that javac compiles:

public class StackoverflowDemoApplication {
    private static Stream getRawStream() {
        return Stream.of(1, 2, 3);
    }

    public static void test() {
        getRawStream().<Integer>map(it -> it + "")
                .forEach(System.out::println);
    }


    public static void main(String[] args) {
        test();
    }
}

but intellij shows an error:

Type arguments given on a raw method in Intellij IDEA

Denis Zavedeev
  • 7,627
  • 4
  • 32
  • 53