okay so on my class diagram it shows
void setVegetable( String veg[] )
String veg[] getVegetables()
Just wondering how I would code the statement for this?
public void setVegetables( String veg[] )
{
}
also how would I write the instance variables?
do I still write it as
private string vegetables = "";
The simple answer is to use a member definition like this:
private String[] vegetables;
And a setter like this:
public void setVegetables( String veg[] ) {
vegetables = veg;
}
However you should keep in mind that a array is modifiable meaning that if you store the array directly like in the setter described above the caller will still be able to modify the content of the array so it's a good practice to copy the array content if you want a better encapsulation. Though this will have impact on performances if you manipulate large arrays.
In this case the setter and getter will look like this
public void setVegetables( String veg[] ) {
vegetables = Arrays.copyOf(veg, veg.length);
}
public String[] getVegetables() {
return Arrays.copyOf(vegetables, vegetables.length);
}
I would change the variable:
private String vegetables;
to an array:
private String vegetables[];
then normally set and get the instance array using the setter and getter methods.
It should be like this :
public void setVegetables( String[] veg ) { }
You can assign values to the local variable when you initialise it like this:
private String[] vegetables = new String[]{"Carrot", "Parsnip"};
As per your class diagram, the instance variable you are looking at is a String array. So the instance member has to be a String[] as well.
The declaration should be like
private String[] vegetables;
public void setVegetables( String vegetables[] ) {
this.vegetables = vegetables;
}
public String[] getVegetables() {
return vegetables;
}
You would need something like
private String[] vegetables;
and the setter method
public void setVegetables( String[] veg ) { this.vegetables = veg; )
or suffer a compile error - An array of String's is not the same as a String.
Related
In a Android application I am making I have an array of instances of a certain class I made, and later in the program I need to use the getter and setter methods from that class on an instance of the class from the array. Do I need to assign the instance of the class from the array to a new class initializer? Here is some code to clear this up:
Class
public class ProfileInformation {
private String console;
private String gamertag;
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getGamertag() {
return gamertag;
}
public void setGamertag(String gamertag) {
this.gamertag = gamertag;
}
}
Array
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
Some instances of ProfileInformation are then added to arraylist, and then I get one of the instances from the arraylist and try to use getGamertag() to set it to a string:
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
The problem is example will equal null. Why is this?
First, an Arraylist is a List, try not to confuse that with actual arrays.
Do I need to assign the instance of the class from the array to a new class initializer?
You don't need to get an element out of the Arraylist, no. You can chain many methods together
String example = ProfTags.get(ProfTags.size()-1).getGamertag();
example will equal null. Why is this?
For the same reason any object is null... You never set it equal to anything else
This code runs on my laptop:
public static void main(String[] args) {
ArrayList<ProfileInformation> ProfTags = new ArrayList<>();
element = new ProfileInformation();
element.setGamertag("Actual Gamer tag value");
ProfTags.add(element);
ProfileInformation profNew = ProfTags.get(ProfTags.size()-1);
String example = profNew.getGamertag();
}
Output is:
Actual Gamer tag value
I guess you didn't call setGamertag(String).
It may be a common question but I couldn't find nice explanation for it. I am trying to understand the encapsulation of reference variables in Java.In the below code:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName();
}
}
Output: bobfred
At first I thought making our field private and providing a getter method, it's a good encapsulation technique. But when I took closer look on it, I saw that when I invoke getName(), I do in fact return a copy, just like Java always does. But, I am not returning a copy of the StringBuilder object. I am returning a copy of the reference variable that point to the one and only StringBuilder object. So, at the point that getName() returns, I have one StringBuilder object and two reference variables pointing to it ( s and s2).
What are the techniques to make it well encapsulated?? A good explanation with code example expected :) . Thanks in advance.
There are two basic approaches I can think of.
The first is to only return immutable values. The caller can then do what he wants without risking the integrity of your object. In your case, the immutable type would be String:
class Special {
private String s = "bob";
String getName() { return s; }
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
String s2 = sp.getName();
s2 += "fred";
// Alternatively: StringBuilder s2 = new StringBuilder(sp.getName()).append("fred");
sp.printName(); // prints "bob"
}
}
Note: If s needs to be a StringBuilder, you can return s.toString().
The other option is to return a mutable value, but create a defensive copy in your getter. In other words, return a separate reference with duplicate data:
class Special {
private StringBuilder s = new StringBuilder("bob");
StringBuilder getName() { return new StringBuilder(s); } // return a copy of s
void printName() { System.out.println(s); }
}
public class TestSpecial {
public static void main (String[] args ) {
Special sp = new Special();
StringBuilder s2 = sp.getName();
s2.append("fred");
sp.printName(); // prints "bob"
}
}
There can be multiple ways to apply encapsulation to mutable object.
By providing copy constructor (in above example new StringBuilder(oldBuilder.toString())
public class Student{
private String name;
public Student(Student s){
this.name = s.name;
}
}
Using prototype pattern with clone method. But copy Constructor is recommend over clone method.
public Student implements Cloneable{
private int rollNo;
private String name;
public Student clone(){
Student s = (Student)super.clone();
s.name = this.name;
s.rollNo = this.rollNo;
return s;
}
}
public class Clazz{
private Map students= new HashMap();
public student getStudent(int rollNo){
Student s = students.get(rollNo);
return s.clone();
}
}
Using immutable form of mutable object. e.g. Collections.unmodifiablecollection().
Whenever we return collection or array, always return read-only form. So modifications to collection will not impact the state of the object.
How can I access my array from a different class? I have 3 classes; Main (where I want to access the array from) FramePanel (my GUI and where the value from UserInputNum is taken from) and StoryArray (where my array is saved).
I need to access the array in the nested If loop in the Main class, this is because I want too save the specific array data to a string and eventually append it into a JTextArea.
Here are the two classes needed:
Main.java
public class Main
{
public static String UserInput;
public static int UserInputNum;
public static void main(String[] args)
{
FramePanel.main();
StoryArray.main();
UserInputNum = Integer.parseInt(UserInput);
if (UserInputNum >= 0)
{
if (UserInputNum <= 399)
{
StoryArray.storyLine[UserInputNum];
}
else
{
}
}
else
{
}
}
}
StoryArray.java
public class StoryArray
{
public static String storyLine[] = null ;
public String[] getStoryLine()
{
return storyLine;
}
public static void main()
{
//String[] storyLine;
storyLine = new String[399];
storyLine[0] ("1")
storyLine[1] ("2")
storyLine[2] ("3")
storyLine[3] ("4")
storyLine[4] ("5")
storyLine[5] ("6")
In another class you can call the array like this:
String value = StoryArray.storyLine[index];
As it is a static public field you can access it directly by StoryArray.storyLine. But as you have a getter ethod I would suggest to make this getter setter static and the array field private and access it through getter method like that: StoryArray.getStoryLine() (to see why read about encapsulation).
You also shouldn't start your class (main) name from lower case, here are standard coding conventions for java language: http://www.oracle.com/technetwork/java/codeconvtoc-136057.html
Once you've called StoryArray.main(), then you should be able to do StoryArray.storyLine[/*element id*/] = "whatever you want" to get or set any element in storyLine. Additionally, you aren't defining any default array values. In StoryArray.main(), you need to have lines of the form storyLine[n] = "n".
I have a class as such:
public interface ControlService extends RemoteJsonService
{
public void myValues( String [] Names, AsyncCallback<Map<String,RegisterValues>> callback);
public class RegisterValues
{
int FirstField;
int SecondField;
//etc. 200 times
I have a string as such:
String[] fieldValues = new String[]{"FirstField", "SecondField", ....}; //200 of these
My attempt at calling upon these fields (the important part is towards the end):
public class RegistersPanel implements TestStandPanel, ChangeHandler
{
private ControlService service_;
public RegistersPanel(){
service_.RegisterValues( Names, new AsyncCallback<Map<String,ControlService.RegisterValues>>()
{
public void onSuccess( Map<String,ControlService.RegisterValues> result )
{
for( String Name : result.keySet() ){
for (String Values : fieldValues){
message+=result.get(Name).getField(Values); //something like this but I can't quite figure out the syntaxt
//message+=result.get(Name).FirstField; this is tedious
}
As you can see, I can't just use getField, and Eclipse is giving me no helpful options - any advice?
I think this is something what you are looking for inside the double for loop,
RegisterValues regValue=reuslt.get(Name);
regValue.getClass().getDeclaredField(Values).getInt(regValue);
This is not the exact solution. This just gets you access to the fields value inside that class.
P.S: that Values would look nice if changed to value
I am creating a helper class in parsing XML elements, so the developer do not need to know the exact name and capitalization of the XML fields.
private static class TagNames{
public static String RESOURCE_ID = "ResourceId";
public static String RESOURCE_NAME = "ResourceName";
public static String RESOURCE_PRICE = "ResourcePrice";
}
This makes it easier to do things like:
someXMLParser.getValueByTagName(TagNames.RESOURCE_ID);
My question is this. If I want to iterate over all the fields declared in class TagNames, how do I do that? Pseudocode:
For tag in TagNames:
someXMLParser.getValueByTagName(tag)
I know I will probably have to restructure all of this. But I can't figure out a way to make the names easily accessible as well as iterable, without any duplication.
Any suggestions?
You're literally asking for a solution based on reflection, but I think a Java Enum may be a better choice in this case. Building on Frederick's example:
public class EnumTest {
public enum Tags {
RESOURCE_ID("ResourceId"),
REOURCE_NAME("ResourceName"),
RESOURCE_PRICE("ResourcePrice");
private final String tagName;
Tags(String tagName) {
this.tagName = tagName;
}
public String getTagName() {
return tagName;
}
}
public static void main(String[] args) {
for(Tags tag : Tags.values()) {
System.out.println("const:" + tag.name()
+ " tagName:" + tag.getTagName());
}
// API user might do e.g.:
// document.getValueForTag(Tags.REOURCE_NAME);
}
}
Although I agree that you should probably use enums or ResourceBundles, here's a solution to your actual question. A method that generates a Map name -> value from all public constants in a given class (the only thing that's missing should be try / catch or throws)
public static Map<String, Object> getConstantValues(Class<?> clazz){
Map<String, Object> constantValues = new LinkedHashMap<String, Object>();
for(Field field : clazz.getDeclaredFields()){
int modifiers = field.getModifiers();
if(Modifiers.isPublic(mod)
&& Modifiers.isStatic(mod) && Modifiers.isFinal(mod)){
constantValues.put(field.getName(), field.get(null));
}
}
return constantValues;
}
You may want to consider using a ResourceBundle instead of a class to store the tag names. May require a little bit of reworking of your code but it will be easier to produce a list of tags compared to what you are doing now, and adding a new tag won't require much work other then adding a line to the properties file.
You can do this quite easily using enum and an accompanying array:
public class Main {
public enum TagName { RESOURCE_ID, REOURCE_NAME, RESOURCE_PRICE }
private static String[] tags = {"ResourceID", "ResourceName", "ResourcePrice"};
public static String getValueByTagName(TagName tag) {
return tags[tag.ordinal()];
}
public static void main(String[] args) {
System.out.println("Calling by getValueByTagName:");
System.out.println(getValueByTagName(TagName.RESOURCE_ID));
System.out.println("Calling TagName.values() for loop:");
for (TagName t : TagName.values()) {
System.out.println(getValueByTagName(t));
}
}
}
Using an enum is a good fit, especially if you use a custom constructor and the built in "values" method:
public class Main {
public static enum TagName {
RESOURCE_ID("ResourceId"),
RESOURCE_NAME("ResourceName"),
RESOURCE_PRICE("ResourcePrice"),
;
private String s;
private TagName(String s) { this.s = s; }
public String toString() { return this.s; }
public static String[] strings() {
List<String> ss = new ArrayList<String>();
for (TagName tagName : TagName.values()) {
ss.add(tagName.toString());
}
return ss.toArray(new String[ss.size()]);
}
}
public static void main(String[] args) {
// Use TagName.values() for the enums, or for strings...
for (String s : TagName.strings()) {
System.out.println(s);
}
}
}
This way you can simply add new tags and they'll automatically get picked up by the "strings" method; for extra performance you could compute that string array just once, statically, since you can't change the set of enums dynamically. You could get even fancier by auto-generating the tag strings from their constant values, if they are really normalized...