I'm getting a compilation error in Eclipse, while using a generic method, which doesn't appear when using javac. I'm guessing it's a compiler option in Eclipse, but I can't see a relevant item in the Preferences window.
The example I'm working with is from Thinking In Java 4th Edition, the relevant code is below, copied and pasted from the downloadable examples from the book's website.
//: generics/Generators.java
// A utility to use with Generators.
import java.util.*;
import net.mindview.util.*;
public class Generators {
public static <T> Collection<T>
fill(Collection<T> coll, Generator<T> gen, int n) {
for(int i = 0; i < n; i++)
coll.add(gen.next());
return coll;
}
public static void main(String[] args) {
Collection<Coffee> coffee = fill(
new ArrayList<Coffee>(), new CoffeeGenerator(), 4);
for(Coffee c : coffee)
System.out.println(c); }
}
Generator, Coffee and CoffeeGenerator are defined elsewhere, but I don't believe they are relevant to my issue.
This code gives me the compiler error: 'The method fill(Collection, Generator, int) in the type Generators is not applicable for the arguments (ArrayList, CoffeeGenerator, int)'.
Any ideas which option I can change to make Eclipse compile the same as when I use javac from the command line?
Many thanks in advance! I did do a search (here and Google) and couldn't find an answer - apologies if this is a repeat.
Code for CoffeeGenerator:
//: generics/coffee/CoffeeGenerator.java
// Generate different types of Coffee:
import java.util.*;
import net.mindview.util.*;
public class CoffeeGenerator
implements Generator<Coffee>, Iterable<Coffee> {
private Class[] types = { Latte.class, Mocha.class,
Cappuccino.class, Americano.class, Breve.class, };
private static Random rand = new Random(47);
public CoffeeGenerator() {}
// For iteration:
private int size = 0;
public CoffeeGenerator(int sz) { size = sz; }
public Coffee next() {
try {
return (Coffee)
types[rand.nextInt(types.length)].newInstance();
// Report programmer errors at run time:
} catch(Exception e) {
throw new RuntimeException(e);
}
}
class CoffeeIterator implements Iterator<Coffee> {
int count = size;
public boolean hasNext() { return count > 0; }
public Coffee next() {
count--;
return CoffeeGenerator.this.next();
}
public void remove() { // Not implemented
throw new UnsupportedOperationException();
}
};
public Iterator<Coffee> iterator() {
return new CoffeeIterator();
}
}
Code for Generator:
//: net/mindview/util/Generator.java
// A generic interface.
package net.mindview.util;
public interface Generator<T> { T next(); } ///:~
Related
I was trying to review some of the Java language using a spark chart I had once bought. Regarding the use of anonymous inner classes they give this example :
Dice rollDice() {
return new Dice() {
int number = (int)( Math.random() * 6 ) + 1;
};
}
Problem is, I do not see how this would work, and can not get the compiler to accept it as a method within another class. The compiler complains about each reference to Dice "symbol can not be found."
Am I not understanding their example correctly or is this completely invalid code? Thanks in advance!
p.s. if this is working code, could someone provide me with an example of how it can be used?
Edit: I have found something that finally makes sense
The syntax for an anonymous inner class is shown below
new SuperClassName/InterfaceName() {
// Implement or override methods in superclass or interface
// Other methods if necessary
}
This above code is passed to a method that takes an instance of Superclass or completely implements the Interface. For instance, a method that has an EventHandlerparameter and we have not already defined a class that implements the handle(ActionEvent e) method.
enlargeButton.setOnAction(
new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
circlePane.enlarge();
}
});
In this way, it will truly be anonymous. I think the example given in Java's own tutorial to be very poor.
It looks like you've mostly answered your own question and you will probably want to go through some full tutorial or documentation to understand things fully, but here are some answers to your immediate questions.
Your first sample code wont compile until you have a Dice class or interface you can extend. So as an example you can get this code to compile:
class Dicey {
interface Dice {
}
Dice rollDice() {
return new Dice() {
int number = (int) (Math.random() * 6) + 1;
};
}
public static void main(String... none) {
Dice dice = new Dicey().rollDice();
// dice.number; <-- not available
}
}
Now you can do this, but as you suspect this is not a very useful things to do (for a few reasons) but the biggest problem is that after you create this anonymous instance there isn't really a way to get to the .number member.
More usually you would have an anonymous subclass implement some methods on the interface, so that you can actually do something with it. So for example
class HelloAnonymous {
interface Hello {
String say();
}
Hello hello(String world) {
return new Hello() {
public String say() {
return world;
}
};
}
public static void main(String... none) {
System.out.println(new HelloAnonymous().hello("world").say());
// prints 'world'
}
}
gives you a way of making fantastically useful Hello objects that can say something. Having said all this, writing anonymous inner classes is fairly old school because functional interfaces now largely replace the need for them. So in this example you could have:
class HelloAnonymous {
#FunctionalInterface
interface Hello {
String say();
}
// old school
Hello hello(String world) {
return new Hello() {
public String say() {
return world;
}
};
}
// with lambda notation
Hello alsoHello(String world) {
return () -> {
return world;
};
}
public static void main(String... none) {
System.out.println(new HelloAnonymous().hello("world").say());
System.out.println(new HelloAnonymous().alsoHello("world").say());
}
}
since I don't know about 'Dice' class I cannot write same method but I try some thing similar to that. It compile and work can access 'number' variable by using reflection. My opinion is it is not very useful. Following is my code:
public class TestClass {
public static void main(String a[]){
TestClass aClass = rollDice();
try {
System.out.println("value of number : " + aClass.getClass().getDeclaredField("number").getInt(aClass));
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
static TestClass rollDice() {
return new TestClass() {
int number = (int) (Math.random() * 6) + 1;
};
}
}
That example is extremely broken. Throw that source away. Try this:
import java.util.Random;
public class DieFactory {
interface Die { int roll(); }
static Die create(long seed) {
Random random = new Random(seed);
return new Die() {
#Override
public int roll() {
return random.nextInt(6) + 1;
}
};
}
// Now you can roll 2 dice pretty easily.
public static void main(String [] args) {
DieFactory.Die die1 = DieFactory.create(42);
DieFactory.Die die2 = DieFactory.create(24);
for (int i = 0; i < 40; i++) {
System.out.println(die1.roll() + die2.roll());
}
}
}
Incidentally, the word "dice" is plural for the singular "die."
Running into a maddening blocking error:
Exception in thread "main" java.lang.Error: Structure.getFieldOrder() on class com.luke.generator.GeneratorEngine$VERSION_INFO returns names ([BuildString, ProtocolMajorVer, ProtocolMinorVer]) which do not match declared field names ([BiuldString, ProtocolMajorVer, ProtocolMinorVer])
at com.sun.jna.Structure.getFields(Structure.java:925)
at com.sun.jna.Structure.deriveLayout(Structure.java:1058)
at com.sun.jna.Structure.calculateSize(Structure.java:982)
at com.sun.jna.Structure.calculateSize(Structure.java:949)
at com.sun.jna.Structure.allocateMemory(Structure.java:375)
at com.sun.jna.Structure.<init>(Structure.java:184)
at com.sun.jna.Structure.<init>(Structure.java:172)
at com.sun.jna.Structure.<init>(Structure.java:159)
at com.sun.jna.Structure.<init>(Structure.java:151)
at com.luke.generator.GeneratorEngine$.<init>(GeneratorEngine.java:108)
at com.luke.generator.connectionVersion(GeneratorEngine.java:297)
at com.luke.generator.Main.main(Main.java:161)
Platform: Intel, Windows 8
JRE 1.7, 32-bit (x86)
Eclipse Kepler, Default encoding UTF-8
jna-4.1.0.jar
32-bit CPP DLL - I can confirm that I am loading the library and calling functions that do not include parameters. I also tried passing WStrings and Strings, but that did not address the issue.
Source:
CPP struct:
typedef struct {
UINT32 ProtocolMajorVer;
UINT32 ProtocolMinorVer;
UI_STRING BuildString; // Build version for the application.
} VERSION_INFO;
CPP Function
DLL_EXPORTS RETURN_TYPES ConnectionVersion (VERSION_INFO &Version) {<body omitted>}
Java code:
//Interface definition
public interface UiApi extends StdCallLibrary {
UiApi INSTANCE = (UiApi) Native.loadLibrary(UiApiPath,UiApi.class);
final String PROTOCOLMAJORVERSION = new String("ProtocolMajorVer");
final String PROTOCOLMINORVERSION = new String("ProtocolMinorVer");
final String BUILDSTRING = new String("BuildString");
public static class VERSION_INFO extends Structure {
public static class ByReference extends VERSION_INFO implements Structure.ByReference {}
public static class ByValue extends VERSION_INFO implements Structure.ByValue {}
public int ProtocolMajorVer;
public int ProtocolMinorVer;
public byte[] BiuldString;
protected List getFieldOrder() {
return Arrays.asList(new String[] { "ProtocolMajorVer","ProtocolMinorVer","BuildString" });
}
}
//Connection
public int Connect(byte[] strServerName);
public int Disconnect();
public int CloseProject();
public int ConnectionVersion(VERSION_INFO result);
public int ConnectionVersion(VERSION_INFO.ByReference result);
public int ConnectionVersion(VERSION_INFO.ByValue result);
}
//Engine.connectionVersion() method
public static int connectionVersion() {
int nReturn = 0;
String str = new String("This is my build version\n");
UiApi uiapilib;
uiapilib = UiApi.INSTANCE;
try {
UiApi.VERSION_INFO.ByReference result = new UiApi.VERSION_INFO.ByReference();
result.ProtocolMajorVer = 0;
result.ProtocolMinorVer = 0;
result.BiuldString = str.getBytes();
nReturn = uiapilib.ConnectionVersion(result);
}
catch (Exception e) {
System.out.println("Error=" + e.getLocalizedMessage());
}
return nReturn;
}
//This is the code in main that results in exception
private static Engine engine;
engine = new GeneratorEngine();
engine.connectionVersion();
I must be missing something basic. Is there something in Eclipse that could possibly be causing the HashSet name comparisons in JNA's Structure.java (line 925) that would result in names not matching? From the exception thrown, these definitions look identical.
Thanks for any tips, guidance, fresh perspectives you can offer.
Check your spelling - the field is called BiuldString not BuildString, you have the i and u reversed.
I'll get right to it.
So I have code that gets a Null Pointer Exception. I've tried looking up what causes it and how to fix it, but that's why I'm confused with this particular code. It was working just fine earlier today and now its throwing the exception. Any help? I'm probably just overlooking something silly but it's quite frustrating. Code follows:
import java.util.*;
import java.io.*;
public class ShopMain<T> {
List<T> stock;
public void Shop() { stock = new LinkedList<T>(); }
public T buy() { return stock.remove(0); }
void sell(T item) { stock.add(item); }
void buy(int n, Collection<? super T>items) {
for (T e : stock.subList(0, n)) {
items.add(e);
}
for (int i=0; i<n; ++i) stock.remove(0);
}
void sell(Collection<? extends T> items) {
for (T e : items) {
stock.add(e);
}
}
public static void main (String[] args) {
ShopMain<Marker> paintballShop = new ShopMain<Marker>();
Console console = System.console();
System.out.println("1 - Test Suite");
String input = console.readLine("Please select the corresponding number to your choice.\n");
if(input.equals("1")){
Stack<Marker> stack = new Stack<Marker>();
Set<Marker> hashset = new HashSet<Marker>();
System.out.println("Test Suite : Tests List, Stack, HashSet");
paintballShop.sell(new Geo3());
paintballShop.sell(new Ego11());
paintballShop.buy();
paintballShop.buy(2, stack); //Stack use
paintballShop.sell(stack); //Stack use
paintballShop.buy(3, hashset); //HashSet
paintballShop.sell(hashset); //HashSet
System.out.println("Tests Complete");
}
}
}
Exception error occurring at runtime:
Exception in thread "main" java.lang.NullPointerException
at ShopMain.sell(ShopMain.java:14)
at ShopMain.main(ShopMain.java:39)
These last bits are just class 'placeholders' for the objects and their parent class.
public class Marker{}
public class Geo3 extends Marker{}
public class Ego11 extends Marker{}
Thanks again for any help.
That's because your List List<T> stock; is still uninitialized. You need to initialize it for you to be able to add, remove elements to/from it. By default, its null and thus, when you try to call a method on it, you get the NullPointerException.
This happens because you don't have a constructor at all. Shop() is not the constructor of your class. A constructor has the same name as the class, and thus you need to have your constructor like this
public ShopMain() { stock = new LinkedList<T>(); }
Incase, Shop() is a valid method, then you need to call this method so that your list is initialized and only then call the other methods.
paintballShop.Shop(); // Call this method to init your list.
change to constructor..
public ShopMain() { stock = new LinkedList<T>(); }
You probably need to change:
public void Shop() { stock = new LinkedList<T>(); }
//doesn't look a method name, may be this is what you missed
to
public ShopMain() { stock = new LinkedList<T>(); }
You don't have a constructor for ShopMain that initializes your List.
Add this:
ShopMain() {
stock<T> = new ArrayList<T>();
}
Basically it comes do to the fact that stock is never initialised. I imagine that the class use to be called Shop
You could change...
public class ShopMain<T> {
List<T> stock;
public void Shop() {
stock = new LinkedList<T>();
}
To...
public class ShopMain<T> {
List<T> stock;
public ShopMain() {
stock = new LinkedList<T>();
}
Which will initialise the List when the class is constructored...
I'm trying to design an undo/redo mechanism to my Chess game.. I decided to use stack data structure which is going to build on an ArrayList.. I also want that my UndoStack and RedoStack classes should be singleton.. However i'm getting
method does not override or implement a method from a supertype
pop() in UndoStack cannot implement pop() in IStackable
return type Move is not compatible with cgas5.Move
where Move is a type-variable:
Move extends Object declared in class UndoStack
error..
Here is my IStackable interface:
package cgas5;
public interface IStackable {
abstract public Move pop();
abstract public void push(Move m);
}
and my UndoStack class
package cgas5;
import java.util.ArrayList;
public class UndoStack<Move> extends ArrayList<Move> implements IStackable {
UndoStack undoStack;
private UndoStack() {
undoStack = new UndoStack();
}
public UndoStack getUndoStack() {
if (undoStack == null) {
undoStack = new UndoStack();
}
return undoStack;
}
#Override
public Move pop() {
Move m = get(size() - 1);
remove(size() - 1);
return m;
}
#Override
public void push(Move m) {
add(m);
}
}
and if it's necessary my Move class:
package cgas5;
public class Move {
private Piece pieceToMove;
private Square currentSquare;
private Square targetSquare;
private Piece capturedPiece;
private Piece promotedPiece;
public Move(){
}
public Move(Piece pieceToMove, Square currentSquare, Square targetSquare){
this.pieceToMove = pieceToMove;
this.currentSquare = currentSquare;
this.targetSquare = targetSquare;
}
public Piece getPieceToMove() {
return pieceToMove;
}
public void setPieceToMove(Piece pieceToMove) {
this.pieceToMove = pieceToMove;
}
public Square getCurrentSquare() {
return currentSquare;
}
public void setCurrentSquare(Square currentSquare) {
this.currentSquare = currentSquare;
}
public Square getTargetSquare() {
return targetSquare;
}
public void setTargetSquare(Square targetSquare) {
this.targetSquare = targetSquare;
}
public Piece getCapturedPiece() {
return capturedPiece;
}
public void setCapturedPiece(Piece capturedPiece) {
this.capturedPiece = capturedPiece;
}
public Piece getPromotedPiece() {
return promotedPiece;
}
public void setPromotedPiece(Piece promotedPiece) {
this.promotedPiece = promotedPiece;
}
}
Thanks in advance..
This is the problem:
public class UndoStack<Move> extends ArrayList<Move>
That's using Move as a generic type parameter, whereas really you don't want a generic type at all - you just want to use Move as the type argument for ArrayList<E>. You want:
public class UndoStack extends ArrayList<Move>
That should fix the problem - although personally I'd strongly recommend using composition instead of inheritance here. (In other words, make your UndoStack type contain an ArrayList<Move> - or something similar - rather than subclassing it.)
Additionally, this is never going to work:
UndoStack undoStack;
private UndoStack() {
undoStack = new UndoStack();
}
That means that to create an UndoStack, you need to create another UndoStack... how do you expect that to happen? You'll currently get a stack overflow exception... why do you need the variable at all?
I'm getting an error that I really can't explain when trying to compile my Java code:
error: constructor MinimaxThread in class MinimaxThread cannot be applied to given types;
MinimaxThread mmt = new MinimaxThread(board.clone(), 2, true);
^
required: no arguments
found: MCBoard,int,boolean
reason: actual and formal argument lists differ in length
The error makes no sense, as I have a constructor that takes an MCBoard, int, and boolean:
public class MinimaxThread implements Runnable {
public MCBoard board;
public int depth;
public HashMap<Tuple, Integer> moveEvals;
boolean cont = true;
boolean verbose = false;
public MinimaxThread(MCBoard board, int initialDepth, boolean verbose) {
this.board = board;
depth = initialDepth;
moveEvals = new HashMap<Tuple, Integer>();
for (Tuple t : board.legalMoves) {
moveEvals.put(t, new Integer(0));
}
this.verbose = verbose;
}
It's an overloaded constructor (there is one with just MCBoard and one with MCBoard and int), but I don't see how that would matter. Any ideas? Here's the calling code:
public static void testMinimax(){
MCBoard board = new MCBoard();
board.move(5,0);
board.move(4,0);
board.move(5,2);
MinimaxThread mmt = new MinimaxThread(board.clone(), 2, true);
mmt.run();
}
edit: board.clone() is overridden:
public MCBoard clone() {
// irrelevant code removed
return new MCBoard(gridClone, turn, legalMovesClone, moveListClone);
}
edit #2: Here is my git repository, for reproducibility:
https://github.com/cowpig/MagneticCave
EDIT: Now that you've given us your github URL, we can see what MinimaxThread really looks like - at least in the latest pushed code:
public class MinimaxThread extends Thread {
public MCBoard board;
public int depth;
}
Yup, I can see why the compiler would complain at that constructor call...
EDIT: Before we knew that MCBoard.clone() was overridden, the answer below made sense. Now, however, I can see no reason why the compiler should complain. Indeed, using the code you've given (but ignoring the actual implementation, which is irrelevant) it all compiles fine:
MinimaxThread.java:
public class MinimaxThread implements Runnable {
public MinimaxThread(MCBoard board, int initialDepth, boolean verbose) {
}
public void run() {
}
}
MCBoard.java:
public class MCBoard {
public MCBoard clone() {
return null;
}
}
Test.java:
public class Test {
public static void main(String[] args) throws Exception {
MCBoard board = new MCBoard();
MinimaxThread mmt = new MinimaxThread(board.clone(), 2, true);
}
}
So I suspect you're not building the code you've presented. Try to build the code above, and if that works, see if you can figure out the difference between that and your actual code.
Original answer
Presumably the compiler "thinks" that board.clone() returns Object, because that's what's declared by Object.clone(). So you need to cast the result to MCBoard:
MinimaxThread mmt = new MinimaxThread((MCBoard) board.clone(), 2, true);
Alternatively, you could override clone() within MCBoard, declaring that it returns MCBoard rather than Object.