0

Check out the following class:

public class Range<T extends Comparable<T>> { public T lower; public T upper; public Range(String range){ Scanner scanner = new Scanner(range); if(scanner.hasNextInt()) this.lower = scanner.nextInt(); if(scanner.hasNextInt()) this.upper = scanner.nextInt(); } public String toString(){ return lower + " - " + upper; } } 

In constructor, I'm trying to construct an object from a string. Values that the creating object contain are in String range. The string has a format like a string that is return from toString method.

This won't work so easily, the error is on last two lines of constructor, and it says: "Type mismatch: cannot convert from int to T." Ofcourse... Because the T type is decided by the user, and Scanner.nextInt() allways returns int. Even if this would work it would work only when T is int. But let's say that I'm okay if it just works when T is int.

Is there any way I can construct object of this class with such String, only when T is int. I doubt there is anything similar to class specialization like in C++.

Do you get what I want, let's say that string is "5 - 10". I want lower to be 5 and upper 10, and they need to be ints. Anyway possible.

5
  • If you only want ints, why have a generic type? Just make lower and upper both int. Commented Nov 26, 2016 at 20:43
  • Why do u want to use generics, when u have the specific type which is int ? Commented Nov 26, 2016 at 20:48
  • I have made this class for all types that extend Comparable, but I get that this constructor can only work when members are ints. If T's are floats then I would like to make special Range(String range) for that case. Commented Nov 26, 2016 at 20:52
  • What is the final objective of this class ? Commented Nov 26, 2016 at 20:54
  • To represent a range.... I also have a method boolean belongs(T value) which returns whether the value belongs in a range. I didn't post it because I didn't think it's important. Commented Nov 26, 2016 at 20:57

1 Answer 1

3

One way to do this generically is to provide a Function<String, ? extends T> which allows you to parse a String to an instance of T.

public Range(String range, Function<String, ? extends T> parser){ Scanner scanner = new Scanner(range); if(scanner.hasNext()) this.lower = parser.apply(scanner.next()); if(scanner.hasNext()) this.upper = parser.apply(scanner.next()); } 

Note that this overall approach isn't particularly good. For one thing, you can't create a range with only an upper bound; and for another, it limits you to input strings which are tokenized by Scanner; and you would be wise to make your fields final, in order to get the nice properties that gives you.

You are much better off doing the parsing outside the Range class (or, at least, outside the constructor). For example, you can use Optional<T> (or maybe null, shudder) to represent each of the bounds, and then declare your constructor like so:

public Range(Optional<? extends T> lower, Optional<? extends T> upper) 

so you can create the range you want, using whatever format to provide the bounds you want - you construct the lower and upper instances before calling the constructor, so you're free to construct those how you like.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.