I have recently started learning java as my first ever step into object oriented programming and have been having trouble with having my objects interact properly, so I have a few questions, which seem to be incredibly simple but for some reason I cannot find the answers elsewhere:
Firstly, I have been trying to have one object read values from another, in this case it is an object called "game" reading attributes from multiple objects called "Item", the only way I can have the game object read any value from the item object is by having a method in the item class which returns the value which I want, and considering that each item has many attributes that I would like the game class to be able to read this simply does not seem like a particularly effective way to do this. So, is there any way to simply read values from an object? for example simply refering to the variable as item1.points, or item2.name, where item 2 is the object name and points is the variable name within the object?
Secondly, When I am assigning values to each item (I have the user assign certain values at the beginning of the game) is there any way to simply loop the same questions asking for values of attributes and have them assigned to my items sequentially? ie item1 then item2 then item3 rather than having selection statements to decide which item I an up to?
basically that is all I am having trouble with at the moment, any help would be greatly appreciated. Also, before anyone asks me to simply look it up, I HAVE been trying to look it up to no avail, however I may simply be using the wrong keywords to search this so any help in that regard would be much appreciated as well.
Thanks
I agree with Kyle about your first question. The java bean standard is based on accessor methods: getters and setters. IDEs like Eclipse help a lot auto generating these methods for you.
About interacting over an object properties you can use the Apacha Commons Beanutils project to do that:
// Copy properties from someObject to myTargetObject
Map attributes = BeanUtils.describe(someObject);
SomeBean myTargetObject = new SomeBean();
for(String propertyName : attributes.keySet()){
System.out.println("Value for attribute " + propertyName + " is " + attributes.get(propertyName));
// Updates target object
BeanUtils.setProperty(myTargetObject, propertyName, attributes.get(propertyName));
}
The answer to your first question is yes any field marked public will be accessible directly, but that defeats the purpose of information-hiding, which is core to OOP.
Your second question is a little bit more difficult. You can technically loop through the attributes on an object like that, but it requires you use reflection which will probably be more work than benefit.
Agree with Kyle. Also you could consider gathering those object.item_n properties into a property collection of some sort (like HashMap<String, String> textualproperties )and iterate over those or whatever.
For your first problem, make sure that both the classes are in the same package and the members are declared either public (not recommended), or protected (better) or don't specify any access specifier (which is a bit more restrictive than protected). If you follow that, both the objects belong to classes defined in the same package can access/modify each others' members without needing getters/setters.
For your second problem use reflection to go through members one by one. Look here:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
It will tell you how to find out about a class' methods, members etc. dynamically.
Related
First post so I hope this is an appropriate type question for this site. If not I'd appreciate it if someone could direct me to a more appropriate place. I'm extremely new at programming. I did a bit in high school and have recently decided to relearn starting with making a text-based survival game in Java7 using Eclipse.
Right now I'm coding the location superclass. The particular function I need help with is this: it needs to be able to keep track of which of 9 regions the user currently "is in" (which is then used in a large number of other classes for many various purposes. The location class also includes functionality for accepting user input to move to a new region, among various other things.) The way I started this was by making a boolean variable for each region and whenever a transition should occur that variable is set to true. But now I'm wondering if this is the most efficient way to do this. I have to take String inputs, run a method to standardize various acceptable answers into one, and then run it through a switch statement that makes the corresponding boolean variable true?
Would it be simpler to simply keep track of the location with a single String variable that gets set as whatever region the player is in? Or would that be more likely to cause errors or complications when coding? Would an array better suit this need? edit: (I just want to thank you guys for people such an open and helpful community. Its really appreciated.)
BIG EDIT: I wanted to further elaborate on what the regions will eventually do. In each region there will eventually be a handful of places the user can go to that are generic with a small number of places unique to each location. Other major superclasses would be altered depending on what region the user is in (example: my "encounters" superclass would have variables that dictate how likely certain encounters are to happen (i.e. chance to a hostile attack) and these variables would be altered depending on the region) but also by other instances (The "Time" superclass would keep track of the day and time of day which would also effect the variables in "encounters".) The current plan was to make a class for each generic place (i.e. Walmart, technology store, grocery, public park, etc.) They would contain different properties depending on the region and would also effect classes like "encounters". I was going to have their properties defined by if/else & switch statements depending on what region the user was in. But now I'm realizing it would make more sense to define their properties when I create the object.
While a lot of people are steering me to enums, some are also suggesting I make classes for each region, (and I am also hearing about interfaces.) If I were to go with the 2nd route I have 3 questions: (a) If the region classes were all subclasses to "Location", then wouldn't I have a problem creating objects for all the generic places inside the region classes (i.e. Walmarts) because the Walmart class can only belong to one superclass? (If not what is the difference between an object being created in a class and the actual relationship between a superclass and its subclasses) (b) If I initialized each region as an object instead of simply recording it with a variable, how would I achieve the original task of remembering which region the user is in (for functions as simple as printing the region out to making alterations to variables in classes like "encounters"). Wouldn't I still need to have some sort of variable to identify the region? And if so, that what practical purpose does creating classes for the region accomplish? (I can see this might still let me make the code cleaner by housing the variables that interact with "encounters" instead of having to use if/else/switch statements inside the "encounters" class (also in this case how could I make the variables in the region classes interact with the variables in "encounters" since neither belong to each other) but anything else?) (c) Would it make more sense to create classes for every region or a single region class that gets defined differently when initialized and WHY?
Finally, I know I may have asked too many questions but could someone please explain to me the different utilities found in enums and interfaces (I'm especially interested in hearing about enums) and now that you know a little bit more, should I be using enums, interfaces, or some sort of classes for the regions? Thank you guys so much!
Enum is very recommended, as stated by Vasily Liaskovsky.
Using int is a great way as well. For example:
int currentRegion;
static final int region1 = 0;
static final int region2 = 1;
static final int region3 = 2;
etc...
Make sure the region1 etc are stated final, so their IDs cannot be changed afterwards, static reference could save memory if you're using multiple location superclass objects, also easier accessible outside the class.
This way to check if you're in a certain region, just use a if statement:
if(currentRegion == region1) {}
To set it:
currentRegion = region1;
Simple as that
I disagree with the usage of an enum here. An enum is great, but not extendable. What if you want to add another region?
So just create classes, and pass them around. They might hold some form of string as identifier (but you should load the proper name from a file that can be localized, anyways).
With a proper class, you can easily add new transitions betwen regions (make your region class a graph) and much more.
Region current = ...;
List<Transition> neighbours = current.getNeighbours();
foreach (Transition t : neighbours)
System.out.println("To the " + transition.getDirection() + " is the " + transition.getTargetName());
// prints e.g. "To the north is the shadowy jungle"
There are a lot of ways todo this, and in an OOP language, you should really try to get into the mindset of using objects instead of setting integer flags or else.
Take a look on enum.
If the list of 9 regions should not grow as game develops, you can describe each of them in hardcoded fashion also utilizing power of objects. Enums can have custom properties and methods weawing them into your architecture, and also enums provide some extra benefits such as == comparison and using in switch blocks.
EDIT
I don't understand why this future addition might make enums a less desirable route
The only way to add an option to enum is to rewrite its class source code. That is, enum options are defined statically and in larger projects when developers should deal with product versions, compatibility, delivering to end-users etc., this could be a pain. In fact, any change in source code of published project is undesirable, since it requires recompilation and full rebuild of at least one (in best case) application module.
The way to deal with it is to move modifiable data into some resource (this can be a file, database table, plugin or anything easily modifiable without full rebuild) and make your application to initialize itself on startup in runtime. Since from this point your program no longer knows that data in advance, statically, there is no way you could define enum describing that data. And in this scenario custom classes (Polygnome's answer) will do the job. Your program reads the resource, creates and initializes objects in runtime that describe your configuration and uses dynamic data.
IMHO, there is almost always tradeoff beween flexibility and complexity. You gain flexibility and freedom to modify region list, but you have to deal with complexity of dynamic solution. Or you decide to use much simpler enums understanding their limited extensibility.
Btw, in order of growing flexibility (and complexity):
raw primitives (int/String) | enums | custom classes
I'm heavily using Java.lang.Class.getField() method which requires a String variable as an argument. The problem I'm facing is when I change field names, that getField() refers to, Eclipse doesn't warn me that argument points nowhere (since it's String) and I end up having methods working improperly unnoticed.
So far I can see two ways out. It's either using try-catch blocks around every getField() call and running application to see what will be the next line to throw an exception. Fix it and watch out for the next exception. Or it's using Find/Replace feature every time I change a field name to manually look for the String value and replace it. Is there a more friendly (i.e. automatic) way to update String parameters in such cases?
Maybe there's a method (which I fail to find) that accepts a full field path as a non-String argument and returns a Field object? Something like turnToFieldObject(car.speed) returning Field object corresponding to speed field so that Eclipse would automatically check if there's such a field car.speed.
PS
First of all, thank you for your replies.
I can see that a lot of you, guys, suggest that I'm using reflection too much. That's why I feel I need to add extra explanation and would be glad to hear suggestions as well.
I'm doing a research about modeling social evolution and I need the entities to evolve new features that they don't have at the start. And it seemed to me that adding new fields to represent some evolutional changes is better understanding wise than adding new elements to arrays or collections. And the task suggests I shouldn't be able to know what feature will be evolved. That's why I rely so heavily on reflection.
AFAIK, there is no such method. You pass a reference (if it's an object) or value (if it's primitive); all data about the variables that they were originally assigned to is not available at runtime.
This is the huge downside of using reflection, and if you're "heavily" using this feature in such way, you're probably doing something wrong. Why not access the field directly, using getters and setters?
Don't get me wrong, reflection has its uses (for example, when you want to scan for fields with certain annotations and inject their values), but if you're referencing fields or methods by their name using a simple string, you could just as well access fields or methods directly. It implies that you know the field beforehand. If it's private, there is probably a reason why it's encapsulated. You're losing the content assist and refactoring possibilities by overusing reflection.
If you're modeling social evolution, I'd go with a more flexible solution. Adding new fields at runtime is (near?) impossible, so you are basically forced to implement a new class for each entity and create a new object each time the entity "evolves". That's why I suggest you to go with one of these solutions:
Use Map<String, Object> to store entities' properties. This is a very flexible solution which will allow you easily add and remove "fields" at the cost of losing their type data. Checking if the entity has a certain property will be a cheap contains call.
If you really want to stick to a million custom classes, use interfaces with getters and setters in addition to fields. For example, convert private String name to interface Named { String getName(); void setName(String name); }. This is much easier to refactor and does not rely on reflection. A class can implement as many interfaces as you want, so this is pretty much like the field solution, except it allows you to create custom getters/setters with extra logic if desperately needed. And determining if entity has a certain property is a entity instanceof MyInterface call, which is still cheaper than reflection.
I would suggest writing a method that use to get your fields supply it a string and then if the exception is thrown notify whatever needs to be notified that it was not valid and if the exception isn't caught return the field.
Although I do agree with the above that reflection should not be used heavily.
I have a bean whose properties I want to access via reflection. I receive the property names in String form. The beans have getter methods for their private fields.
I am currently getting the field using getDeclaredField(fieldName), making it accessible by using setAccessible(true) and then retrieving its value using get.
Another way to go about it would be to capitalize the field name and add get to the front of it, and then get the method by that name from the class and finally invoke the method to get the value of the private field.
Which way is better?
EDIT
Perhaps I should explain what I mean by "better"... By "better", I mean in the sense of best-practices. Or, if there are any subtle caveats or differences.
You may want to take a look at the Introspector class, its a nice wrapper if you want to only deal with properties which have been exposed, you can get a BeanInfo object and then call getPropertyDescriptors(), for example:
final BeanInfo info = Introspector.getBeanInfo(clazz);
for (PropertyDescriptor prop : info.getPropertyDescriptors()) {
final Method read = prop.getReadMethod();
if (read != null) {
// do something
}
}
It depends of your use, but in general I would prefer to use the getter as this is the "normal" way and will in more cases do the thing the developer of the class expects gets done.
In principle, if the developer of the class has made the field private he is free to do as he pleases, like for instance removing it later if it can be calculated in another way. Then the fieldaccess will break, hopefully immediately, if you are unlucky 3 months later when nobody remembers anymore.
Note that there a libraries like apache commons BeanUtils (I believe there is one in Spring too) which does that for you and offer a more sane interface, like a hash map for example.
Possibly using the getter method, as it may have additional behaviour besides just returning the property's value. However this depends on the class.
Better in what way?
You could write a 20 line unit test to see which is faster. You could write both and look at them to see which is easier to read. If one way is both easier to read and faster, go for it. If not, you will have to pick your poison...
Let's say I've got a class called House with the two fields
name
address
Each of these fields has got a getter and a setter.
Now I want another method in the House class called setValues. This method should set the fields with properties from a passed object of a different type.
There would be two ways on how to create this method. First way:
private void setHouse(HouseTransfer transer){
name = transfer.getName();
address = transfer.getAddress();
}
Or the second option:
private void setHouse(HouseTransfer transer){
setName(transfer.getName());
setAddress(transfer.getAddress());
}
Which one is more "best practice"?
At a certain level of granularity, software design is more subjective matter than one of black-and-white absolutes. I do not believe there is an absolute "best practice" here.
That being said, I personally would use the second form. The basic idea of having a setter method is that at some point you might need some some special logic around setting that value (e.g. formatting input, sanitation, validation, etc). So it makes the most sense to always rely on any such logic being in one central place, rather than scattered throughout you code anywhere this variable is set.
If you have a truly trivial example, where the setter is simply setting the value and know absolutely that no other logic will ever be added, then you could certainly use the first form for simplicity. Put there's not real performance hit to the second form, so I personally would just use that.
I would use the individual getters/setters inside of the setHouse method (which is your second option).
The fact that you have setters indicates that there is some kind of encapsulation involved around that operation. Rather than re-write the code to enforce that encapsulation, re-use what you already have.
Jon's answer to that question (Taken from another question about using getters/setters which is not a duplicate to this one)
You don't always need getters/setters, but if you have some, there's usually a good reason why you've implemented them and in that case: use them.
Perhaps if you are getting and setting in two different places you might consider factoring out your getter and setter to a common interface. This can make later customisations easier, right?
hello guys i'm not sure if the title is descriptive enough.what i mean is creating an enum
like so
public enum Test{
ONE, TWO ,THREE
}
this looks like hard coded.if for some reason i need to add the FOUR some certain business rules evolution reasons.should i code it and deploy it again?
isn't a way to let it pick the elements from a file , spring config for example or property file?
THanks for reading.
If the enum value doesn't explicitly exist in code, how could you ever use it? Test.Four would not compile. Any code which could somehow reference Test.Four would be invalid and would crash, until the point in time when the file is read and the new values are added.
You can, of course, use arrays or collections of values and manipulate those at runtime - load them from a file or from the database or whatever - but not enums.
I asked a similar question here. The content may be of interest.
The concensus seemed to be that Java's enum type is static by design. If you need something that can be altered at runtime, you should ideally use a different data structure.
The less preferred ideas were along the lines of extending Enum, etc.
You may store in a database table.