I am trying to brushup java after a long time.
Any help is much appreciated.
For demonstration I have Animal Class that has an array of innerclass of Organs.
public class Animal
{
String nameOfAnimal;
Organs [] vitalOrgans = new Organs[3];
public Animal()
{
}
public String getNameOfAnimal() {
return nameOfAnimal;
}
public void setNameOfAnimal(String nameOfAnimal) {
this.nameOfAnimal = nameOfAnimal;
}
#Override
public String toString() {
return "Animal{" + "nameOfAnimal=" + nameOfAnimal + "}";
}
class Organs{
String nameOfOrgan;
public String getNameOfOrgan() {
return nameOfOrgan;
}
public void setNameOfOrgan(String nameOfOrgan) {
this.nameOfOrgan = nameOfOrgan;
}
#Override
public String toString() {
return "Organs{" + "nameOfOrgan=" + nameOfOrgan + '}';
}
}
}
Now in driver file when I make call there is no syntactical error but I get "Exception in thread "main" java.lang.NoSuchFieldError: vitalOrgans"
Animal mamal = new Animal();
mamal.setNameOfAnimal("Chimp");
mamal.vitalOrgans[0].setNameOfOrgan("Heart");
System.out.println(mamal.vitalOrgans[0].getNameOfOrgan());
What would be the way to make this (or similar idea) to work.
Thanks.
You would need to initialize the vitalOrgrans with new Organs(). Like:
public Animal() {
for (int i = 0; i < vitalOrgans.length; i++) {
vitalOrgans[i] = new Organs();
}
}
Because when you say :
Organs[] vitalOrgans = new Organs[3];
You are creating an array of 3 null Organs. Hence the null pointer exception, when accessing "vitalOrgans[i].".
Taking the relevant bit of code:
public class Animal
{
//...
Organs [] vitalOrgans = new Organs[3];
//...
}
Since your declaration of vitalOrgans was never given an access modifier (i.e. one of private, public, protected) it took on default access, which means only other classes in the same package can see it. Since your other block of code is not in the same package, it cannot see the field.
A minimally viable modification to just make it work would be to set the access to public:
public class Animal
{
//...
public Organs [] vitalOrgans = new Organs[3];
//...
}
While this works, it's not necessarily the best solution, as if you ever change how vitalOrgans is represented, or need to perform any validation, those edits would have to be done throughout the application. Thus, a better solution (and also, a major stylistic convention in Java for those exact reasons) is to make it (and all your fields, in fact) private and access via methods:
public class Animal {
private String nameOfAnimal;
private Organs[] vitalOrgans = new Organs[3];
//...
public Organs[] getVitalOrgans() {
return vitalOrgans;
}
//Alternative accessor that fetches only one organ.
public Organs getVitalOrgan(int index) {
if(index >= 0 && index < vitalOrgans.length)
return vitalOrgans[index];
else
return null;
}
public void setVitalOrgans(Organs[] vitalOrgans) {
this.vitalOrgans = vitalOrgans
}
//...
}
Your caller could then access Organs via either form of the get method (note, you probably want Organs to be public):
Animal.Organs futureMammalHeart = mamal.getVitalOrgan(0); //Animal.Organs due to Organs being an inner class.
if(futureMammalHeart != null) //Demonstration of null check. Safety first!
futureMammalHeart.setNameOfOrgan("Heart");
Animal.Organs[] mammalianVitalOrgans = mamal.getVitalOrgans();
if(mammalianVitalOrgans != null) //Just in case...
System.out.println(mamal.mammalianVitalOrgans[0].getNameOfOrgan());
Also, as Ari mentioned in his answer, don't forget to initialize the organs in your array, otherwise you will get a NullPointerException!
Related
I'm writing a messaging system to queue actions for my program to execute. I need to be able to pass various objects by the messages. I currently have a Msg object that accepts (Action enum, Data<?>...object). The Data object is intended to be a wrapper for any object I might pass.
Currently the Data object uses this code, with generics:
public class Data<T> {
private T data;
public Data(T data){
this.data = data;
}
public T getData(){
return data;
}
}
The Msg object takes Data<?>... type, so Msg has a Data<?>[] field.
If getData() is called on a Data<?> object, it returns the Object type. Obviously not ideal.
I need to be able to pass, say, Image objects as well as String objects. I'm certain there's a better way of passing arbitrary data.
The reason you're having trouble is that you're trying to get the static typing system of Java to do something that it can't. Once you convert from a Data<T> to a Data<?>, whatever T was is effectively lost. There's no clean way to get it back.
The quickest way to get it to work (from what you have right now) is to start throwing casts everywhere, like this:
Data<?> d = new Data("Hello");
String contents = (String)d.getData();
This is kind of a terrible idea, so let's go back to the drawing board.
If (ideally), you have all of the types you could ever need ahead of time (i.e. every Data is either a String or an Image or an Integer), then you can pretty easily (though it's a bit tedious) define a Sum type (aka a union if you're coming from C) of the different types of data you'll have to handle. As a class invariant, we assume that exactly one of the fields is non-null, and the rest are null. For this example I'll assume it can be either a String, an Image, or an Integer, but it's fairly simple to add or remove types from Data as necessary.
public class Data {
private Image imgData;
private String stringData;
private Integer intData;
public Data(Image img) {
this.imgData = img;
}
public Data(String stringData) {
this.stringData = stringData;
}
public Data(Integer intData) {
this.intData = intData;
}
public boolean isImage() {
return imageData != null;
}
public boolean isInteger() {
return intData != null;
}
public boolean isString() {
return stringData != null;
}
public Image asImage() {
if(! isImage()) throw new RuntimeException();
return imgData;
}
public Image asString() {
if(! isString()) throw new RuntimeException();
return stringData;
}
public Image asInt() {
if(! isInt()) throw new RuntimeException();
return intData;
}
}
One necessary side effect is that we cannot wrap null without causing exceptional behavior. Is this is desired, it isn't too difficult to modify the class to allow for it.
With this Data class, it's pretty easy to do if-else logic to parse it.
Data d = ....... //Get a data from somewhere
if(d.isImage()) {
Image img = d.asImage();
//...
} else if (d.isString()) {
String string = d.asString();
//...
} else if (d.isInteger()) {
Integer i = d.asInt();
//...
} else {
throw new RuntimeException("Illegal data " + d + " received");
}
If you call getData().getClass() you will get the class or type that was passed, which doesn't seem to me to be the same as an Object. You might not know what you are getting, but you can either find out or define a common interface for everything you might pass. You could for example, call toString() or getClass() on anything passed. Your question is that you are passing any conceivable object, so my question is what are you going to do with it? If you are going to serialize it into a database you don't need know anything about what type it is, otherwise you can test it or call a common interface.
public class PlayData {
class Msg {
private List<Data<?>> message = new ArrayList<Data<?>>();
public void addData(Data<?> datum) { message.add(datum); }
public void printTypes() { for ( Data<?> datum: message ) { System.out.println(datum.getData().getClass()); } }
}
class Data<T> {
private T value;
public Data(T value) { this.value = value; }
public T getData() { return value; }
}
class Listener {
public void receive(Msg msg) { msg.printTypes(); }
}
class Sender {
private Listener listener;
public Sender(Listener listener) { this.listener = listener; }
public void send(Msg msg) { listener.receive(msg); }
}
class MyPacket {
int i;
public MyPacket(int i) { this.i = i; }
}
public static void main(String[] args) throws Exception { new PlayData().run(); }
public void run() throws Exception {
Sender sender = new Sender(new Listener());
Msg msg = new Msg();
msg.addData(new Data<String>("testing") );
msg.addData(new Data<MyPacket>(new MyPacket(42)) );
sender.send(msg);
}
}
In my program, the user needs to input what type of players the game will have. The players are "human", "good" (for a good AI), "bad" (for a bad AI) and "random" (for a random AI). Each of these players have their own class that extend one abstract class called PlayerType.
My struggle is mapping a String to the object so I can A) create a new object using the String as sort of a key and B) get the related String from an object of its subclass
Ultimately, I just want the implicit String to only appear once in the code so I can change it later if needed without refactoring.
I've tried using just a plain HashMap, but that seems clunky with searching the keys via the values. Also, I'm guessing that I'll have to use the getInstance() method of Class, which is a little less clunky, which is okay if it's the only way.
What I would do is create an enum which essentially functions as a factory for the given type.
public enum PlayerTypes {
GOOD {
#Override
protected PlayerType newPlayer() {
return new GoodPlayer();
}
},
BAD {
#Override
protected PlayerType newPlayer() {
return new BadPlayer();
}
},
RANDOM {
#Override
protected PlayerType newPlayer() {
return new RandomPlayer();
}
};
protected abstract PlayerType newPlayer();
public static PlayerType create(String input) {
for(PlayerTypes player : PlayerTypes.values()) {
if(player.name().equalsIgnoreCase(input)) {
return player.newPlayer();
}
}
throw new IllegalArgumentException("Invalid player type [" + input + "]");
}
)
Because then you can just call it like so:
String input = getInput();
PlayerTypes.create(input);
Of course, you'll get an IllegalArgumentException which you should probably handle by trying to get the input again.
EDIT: Apparently in this particular case, you can replace that loop with just merely
return PlayerTypes.valueOf(input).newPlayer();
And it'll do the same thing. I tend to match for additional constructor parameters in the enum, so I didn't think of using valueOf(), but it's definitely cleaner.
EDIT2: Only way to get that information back is to define an abstract method in your PlayerType class that returns the PlayerTypes enum for that given type.
public class PlayerType {
public abstract PlayerTypes getType();
}
public class GoodPlayer extends PlayerType {
#Override
public PlayerTypes getType() {
return PlayerTypes.GOOD;
}
}
I like the answer provided by Epic but I don't find maps to be clunky. So it's possible to keep a map and get the constructor call directly.
Map<String, Supplier<PlayerType> map = new HashMap<>();
map.put("human", Human::new);
Human h = map.get("human").get();
The two main options I can think of:
Using Class.newInstance(), as you mentioned (not sure if you had this exact way in mind):
// Set up your map
Map<String, Class> classes = new HashMap<String, Class>();
classes.put("int", Integer.class);
classes.put("string", String.class);
// Get your data
Object s = classes.get("string").newInstance();
You could use Class.getDeclaredConstructor.newInstance if you want to use a constructor with arguments (example).
Another option is using switch:
Object getObject(String identifier) {
switch (identifier) {
case "string": return new String();
case "int": return new Integer(4);
}
return null; // or throw an exception or return a default object
}
One potential solution:
public class ForFunFactory {
private ForFunFactory() {
}
public static AThing getTheAppropriateThing(final String thingIdentifier) {
switch (thingIdentifier) {
case ThingImplApple.id:
return new ThingImplApple();
case ThingImplBanana.id:
return new ThingImplBanana();
default:
throw new RuntimeException("AThing with identifier "
+ thingIdentifier + " not found.");
}
}
}
public interface AThing {
void doStuff();
}
class ThingImplApple implements AThing {
static final String id = "Apple";
#Override
public void doStuff() {
System.out.println("I'm an Apple.");
}
}
class ThingImplBanana implements AThing {
static final String id = "Banana";
#Override
public void doStuff() {
System.out.println("I'm a Banana.");
}
}
I have multiple classes that all inherit from the same Block class, and want to instantiate one of them based on a variable value.
Here is what I did for now:
public enum MapCases {
FLOOR (Floor.class), // These are all subclass of my Block class
WALL (Wall.class),
ROCK (Rock.class);
private Class<?> blockType;
MapCases (Class<?> pointing) {
this.block = pointing;
}
public Class<?> getType () {
return this.blockType;
}
};
Then later, I try to instantiate them given some data:
private Block[] blocks; // Array of the mother type
...
blocks = new Block[data.length]; // data is an int array
for (int i = 0; i < data.length; i++) {
int choice = data[i];
Class<?> blockType = MapCases.values()[choice].getType();
blocks[i] = new blockType(); // blockType is of unresolved type
}
But Eclipse shows me an error saying it can't resolve blockType to a type (which seems logical given the fact that java don't know yet the type).
How could I achieve what I am trying to do?
You shouldn't need reflection to do this. Consider this instead:
public enum MapCases {
FLOOR {
#Override
public Block makeBlock() {
return new Floor();
}
},
WALL {
#Override
public Block makeBlock() {
return new Wall();
}
},
ROCK {
#Override
public Block makeBlock() {
return new Rock();
}
};
public abstract Block makeBlock();
}
In this case, the enum itself acts as the factory instead of the Class token it was holding.
Note that if you did want to stick with the Class token, it should be typed as Class<? extends Block>, as Elliott Frisch points out in the comments. Then a call to blockType.getConstructor().newInstance(), which GGrec's answer demonstrates, will return an instance of Block.
Use reflection to create a new instance from the class blueprint.
Pattern:
Class.forName(className).getConstructor().newInstance();
Your case:
blocks[i] = blockType.getConstructor().newInstance();
I have a class that i'm uses a generic Type that extends the interface zwave
everything is fine until i try to access a zwave variable for some reason the rm.keyword gives a "NullPointerException". if I cast it to the class scene it works, but that is not what I want
public <T extends zwave> T Find(List<T> Zwave,List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T rm: Zwave)
{
//*** problem is here
//rm.keyword is always gives a NullPointerException unless i cast it to a class
if (rm.keyword.equals( str.toLowerCase()))
{
return rm;
}
}
}
}
return null;
}
//here is the interface
interface zwave
{
public String keyword="";
public String zwaveID="";
}
//here is a class that implements the interface
public class Scene implements zwave
{
String name;
String keyword;
String zwaveID;
public Scene(String Name,String Keyword,String ZwaveID)
{
name= Name;
zwaveID= ZwaveID;
keyword = Keyword;
}
}
edit
Working code
//search class
public <T extends searchable> T Find(List<T> searchableclasses, List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T searchable: searchableclasses)
{
for(String key: searchable.GetKeywords())
{
if ( key.equals(str.toLowerCase()))
{
return searchable;
}
}
}
}
}
return null;
}
//abstract class
abstract class searchable
{
String[] keywords; //using array so i can use java's param ability
public List<String> GetKeywords()
{
return new ArrayList(Arrays.asList(keywords));
}
}
//actual class
public class Scene extends searchable
{
String name;
String zwaveID;
public Scene(String Name,String ZwaveID,String... Keywords)
{
name= Name;
zwaveID= ZwaveID;
keywords = Keywords;
}
}
If you don't wanna cast you can do some thing like this:
public <T extends zwave> T Find(List<T> Zwave,List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T rm: Zwave)
{
if(rm instanceof Scene){
Method method=null;
try {
method = rm.getClass().getMethod("getKeyword");
if ( method.invoke(rm).equals( str.toLowerCase()))
{
return rm;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
NOte:define getKeyword method in Scene class:
I can customize it more with the help of java.lang.reflect. You would not even need to use instance of Scene. But I think you can do it yourself. And hope it will help.
use Reflection API to call at run time.
You need to be using a getter method. When you say rm.keyword, that's referring to a constant (zwave.keyword), which is the empty string. When you cast to Scene, the compiler sees that it's a field and looks it up instead.
Generally, you should make fields like name and keyword private unless you have a specific reason not to and use getter and setter methods to manipulate them.
The variables defined in the interface are final static public even though you didn't explicitly define. When the variable is final, once the value is assigned you cannot reassign it again.
Since you have defined as empty string ("") it will take that value. But you define the variable again in Scene class. So when you cast to Scene object will refer this variable and not the variable in the interface. Otherwise it refers to interface variable.
Is there any way in java to check if a certain method was called inside another method? I am testing a class and the method I am having trouble with plays sound and there is virtually no way of getting the audio file that is played(private attribute inside an inner class) without changing the code. However the way the method plays sounds is it calls a method that plays a single sound (playSadMusic, playHappyMusic, etc). Those methods are in an interface that I have to create a mock object for. I'm a little stuck on how I would exactly go about testing this. Any thoughts? Any other ideas on how I could possibly test this other than check if a certain method was call are welcome.
I am using JMock 2.6.0 and JUnit 4
the audio inteface
public interface StockTickerAudioInterface {
public abstract void playHappyMusic();
public abstract void playSadMusic();
public abstract void playErrorMusic();
}
anther interface I have to create a mock for
public interface StockQuoteGeneratorInterface {
public abstract StockQuoteInterface getCurrentQuote() throws Exception;
public abstract String getSymbol();
public abstract void setSymbol(String symbol);
public abstract StockQuoteGeneratorInterface createNewInstance(String symbol);
}
the class being tested
public class StockQuoteAnalyzer {
private StockTickerAudioInterface audioPlayer = null;
private String symbol;
private StockQuoteGeneratorInterface stockQuoteSource = null;
private StockQuoteInterface lastQuote = null;
private StockQuoteInterface currentQuote = null;
public StockQuoteAnalyzer(String symbol,
StockQuoteGeneratorInterface stockQuoteSource,
StockTickerAudioInterface audioPlayer)
throws InvalidStockSymbolException, NullPointerException,
StockTickerConnectionError {
super();
// Check the validity of the symbol.
if (StockTickerListing.getSingleton().isValidTickerSymbol(symbol) == true){
this.symbol = symbol;
} else {
throw new InvalidStockSymbolException("Symbol " + symbol
+ "not found.");
}
if (stockQuoteSource == null) {
throw new NullPointerException(
"The source for stock quotes can not be null");
}
this.stockQuoteSource = stockQuoteSource;
this.audioPlayer = audioPlayer;
}
public double getChangeSinceLast() {
double retVal = 0.0;
if (this.lastQuote != null) {
double delta = this.currentQuote.getLastTrade() - this.lastQuote.getLastTrade();
retVal = 100 * (delta / this.lastQuote.getLastTrade());
}
return retVal;
}
public double getChangeSinceYesterday() {
double delta = (this.currentQuote.getLastTrade() - this.currentQuote
.getClose());
return 100 * (delta / this.currentQuote.getClose());
}
public void playAppropriateAudio() {
if ((this.getChangeSinceYesterday() > 2)
|| (this.getChangeSinceLast() > 0.5)) {
audioPlayer.playHappyMusic();
}
if ((this.getChangeSinceYesterday() < -2)
|| (this.getChangeSinceLast() < -0.5)) {
audioPlayer.playSadMusic();
}
}
}
If you use Mockito you can use verify() to check the number of times a method was called. Use it like this:
verify(mockedObject, times(1)).methodToValidate();
You can check if methodToValidate() was called with a specific string, e.i verify(mockedObject, times(1)).methodToValidate("a specific value"); or you can use it with anyString() like this: verify(mockedObject, times(1)).methodToValidate(anyString());.
Unless this method is called with your specified paramterer, the test will fail
Read more about verify here.
UPDATE
Since your edited post states that you are using jMock, a quick googeling showed me that it is possible to achieve a similar behaviour with jMock and it's expect method. It's used as below:
mockedObject.expects(once()).method("nameOfMethod").with( eq("An optional paramter") );
More detailed explanation can be found by reading jMocks getting started page.
say you have a method child() which is called in parent()
public void parent() {
child();
}
In child() to get the last method it got invoked from, you can use StackTraceElement
public void child() {
StackTraceElement[] traces = Thread.currentThread().getStackTrace();
boolean check = false;
for(StackTraceElement element : traces) {
if(check) {
System.out.println("Calling method - " + element.getMethodName());
}
if(element.getMethodName().equals("child")) {
check = true;
}
}
}
If you are writing a mock object with the methods you want to check whether they were called, you can implement the methods in a way they raise some flag when they are called, for example
public void playHappyMusic() {
this.wasCalled = true;
}
wasCalled being a public (or with getters) class variable. Then you just check the flag.
Provide you are in the same thread as the calling method, you can check the stack trace in any given moment this way:
Thread.currentThread().getStackTrace()
You can see what method are called doing it like this:
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
For example:
public class Test {
public static void main (String[]s){
Test test = new Test();
test.makeTest();
}
public void makeTest(){
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
System.out.println(ste);
}
}
results in
java.lang.Thread.getStackTrace(Unknown Source)
Test.makeTest(Test.java:17)
Test.main(Test.java:11)