1.11M Members

Java Generics Question

 
0
 

I'm trying to create a class that reads in a set of numbers from a file, stores them in a generic array, and then sorts them using the generic bubbleSort method. I usually write in C++ and the switch from templates to generics hasn't been easy. I'm fairly certain my bubbleSort method is correct, but I'm not sure what exactly is causing the problem. Thanks in advance for the help. Here is the error message:

Bound mismatch: The generic method bubbleSort(T[], int) of type MySort<T> is not applicable for the arguments (T[], int). The inferred type T is not a valid substitute
for the bounded parameter <T extends Number & Comparable<T>>

import java.util.*;
import java.io.*;

public class MySort<T>{
	
	/**
	 * @param args
	 */
	public static <T extends Object> void main(String[] args) {
		// TODO Auto-generated method stub
		int count = 0;
		T array[] = (T[]) new Object[80];
		
		try {
			FileReader fr = new FileReader("tester.txt");
			Scanner input = new Scanner(fr);
			while(input.hasNext()){
				array[count] = (T) input.nextLine();
				count++;
			}
			bubbleSort(array, count); // the method call is where the error occurs
			
		} 
		catch (FileNotFoundException e) {
			System.out.println("File not Found");
		} 

	}
	
	public static <T extends Number & Comparable<T>> void bubbleSort(T[] array, int size) {
		int swap;
		do{
			swap = 0;
			for (int i = 0; i < size-1; i++) {
				if((array[i]).compareTo(array[i+1]) > 0) {
					T temp = array[i];
					array[i] = array[i+1];
					array[i+1] = temp;
					swap++;
				}
			}
		}
		while(swap != 0);
	}

}
 
0
 

The array you pass as parameter is of <T extends Object>, but the method signature requires <T extends Number & Comparable<T>>
A type of Object is not a valid substitute for a type of (Number that implements Comparable).
You need to define the array that you pass as parameter to be of a type that is a Number or a sub-class of Number, and which also implements Comparable, eg Integer

 
0
 

Okay, that makes sense, however I'm at a loss for how to go about taking in any Number type object from the file. I know there are functions such as .nextInt(), but is there a way that function that can receive generics from a file? Sorry if what I'm saying doesn't make sense, I can't think of a proper way to word my question.

 
0
 

Good morning.
I'm having difficulty understanding what you want to achieve using Java generics. I don't use C++ so I guess we have a terminological disconnect. GeEnerics in Java are a compile-time thing, so "receive generics from a file [at run time]" doesn't compute. Perhaps you can explain the requirement in ordinary English for me?

 
0
 

Okay, let me try to explain this a little better. I have the generic array as created in line 12. I want to read in numbers from a file and store them in this array. I know that Scanner has methods such as nextInt(), but is there a method that will let me read in any object that extends the Number class. (Say I have a file containing the numbers 1, 4, 5, 3, 2; how would I go about storing those in my generic array?)

 
0
 

Sc.NextLine(); would read any and everything.
String stuff = sc.nextLine(); (is this what you mean by generic? :S )
a user could type in "jdiofhdoifh44545454" and it would be stored as a string..... Im not sure if that helped :(

 
0
 

I cannot use nextLine() because my T[] array can only hold objects that extend number (Integer, Double, Float, etc..) is there a way to read in Objects rather than primitive types when using numbers. (Integer i = 1 rather than int i = 1, using the Scanner class)

 
0
 

I may have figured it out although it seems a bit wasteful in terms of space and time complexity, maybe this will help to understand what I'm trying to do though. I changed my array to an ArrayList and I'm testing the input and making decisions based on that rather than just letting the compiler figure it out.

int count = 0;
		ArrayList<T> array = new ArrayList<T>();
		
		try {
			FileReader fr = new FileReader("tester.txt");
			Scanner input = new Scanner(fr);
			if(input.hasNextInt()){
				System.out.println("Using Integer Method");
				while(input.hasNextInt()){
					Integer i = input.nextInt();
					array.add(count, (T) i);
					count++;
				}
			}
			else if(input.hasNextDouble()){
				System.out.println("Using Double Method");
				while(input.hasNextDouble()){
					Double i = input.nextDouble();
					array.add(count, (T) i);
					count++;
				}
			}
			else if(input.hasNextFloat()){
				System.out.println("Using Float Method");
				while(input.hasNextFloat()){
					Float i = input.nextFloat();
				    array.add(count, (T) i);
				    count++;
				}
			}
 
0
 

Not sure why you are doing this with generics; they're all numbers, right? Just read them all in as double.

import java.io.BufferedReader;
import java.util.ArrayList;


public class BubbleSort {

	private ArrayList<Double> list = new ArrayList<Double>();
	
	public BubbleSort(String filename) {
		readFile(filename);
		sortData();
	}
	
	private void readFile(String filename) {
		BufferedReader br = Utility.openFile(filename);
		
		while (Utility.hasNext(br)) {
			list.add(Double.parseDouble(Utility.readLine(br)));
		}
		
		Utility.closeFile(br);
	}
	
	private void sortData() {
		for (int i = 0; i < list.size(); i++) {
			for (int j = list.size() - 1; j > i; j--) {
				if (list.get(j - 1) > list.get(j)) {
					double temp = list.get(j);
					list.set(j, list.get(j - 1));
					list.set(j - 1, temp);
				}
			}
		}
	}
	
	public static void main(String[] args) {
		new BubbleSort("src/data.txt");
	}
}

I use Utility class to open and read files, something like this:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;


public class Utility {
	
	public static BufferedReader openFile(String filename) {
		try { return new BufferedReader(new FileReader(filename)); }
		catch (IOException e) { return null; }
	}
	
	public static void closeFile(BufferedReader reader) {
		try { reader.close(); }
		catch (IOException e) { } 
	}
	
	public static String readLine(BufferedReader reader) {
		try { return reader.readLine(); } 
		catch (IOException e) { return null; }
	}
	
	public static boolean hasNext(BufferedReader reader) {
		try { return reader.ready(); } 
		catch (IOException e) { return false;}
	}
}
 
0
 

I understand its much simpler to do without generics, but I'm trying to get a grasp for generics since its such a significant difference from templates in C++ and I'm trying to become more proficient with Java. I was mostly just inquiring about file io in regards to generics and ArrayLists/Arrays rather than the simplest solution to problem.

 
0
 

Maybe the step that you are missing is that a generic type needs to be replaced by a concrete type at some stage. eg You have a class C <T extends Number>, at some stage you need to create new instance, supplying a concrete type for T eg new C<Integer>();
Within that instance the references to T are effectively replaced by Integer (OK, oversimplified, but one step ata time...)
Similarly with a generic method the generic type is inferred from the actual type(s) of the parameter(s).

The biggest impact of generics has been on Java Collections. Before Java 1.5 collections just contained Objects, so there was no compile-time checking of what was put into them, and anything taken from the collection had to be cast to the appropriate class with an unchecked run-time cast that could fail.

ArrayList a = new ArrayList();
a.add("ABC"); 
a.add(new JButton());  // legal
String s = <String> a.get(i);  // uncheckable at compile time

With generics this becomes clean and safe

ArrayList<String> a = new ArrayList<String>();
a.add("ABC"); 
a.add(new JButton()); // compile error
String s = a.get(i);  // type checked at compile time, no cast needed
You
This article has been dead for over six months: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: