How to instantiate and work with objects containing other objects? [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I'm trying to use object oriented design and it's a bit confusing. Let's say I have 3 separate objects
public class Tool{
String name;
Float weight;
}
public class Drawer{
String name;
Tool[] tool;
}
public class Toolbox{
String name;
Drawer[] drawer;
public void setDrawers(String[] drawers) {
for(int i = 0; i < drawers.length; i++) {
drawer[i].name = drawers[i];
}
}
}
So a Tool has a String and Float. Drawer has a String and an array of Tools. Toolbox has a String and array of Drawers.
So let's say in my main code I say...
Toolbox myBox = new Toolbox();
myBox.setDrawers(drawers);
I'm getting null pointer issues. What's the proper way to instantiate everything if I want to instantiate a toolbox? Each class is in a separate Java file is this ok, or should they be in one file? Since all classes are in the same app do I need to use the import statement? What would my Constructors look like? Is there anything else I'm missing? Thanks for the help.
Please do not mark this as a duplicate of the "null pointer" question. That does not address objects that contain arrays of other objects and how to instantiate everything.

Here's a more standard way to do it.
public class Tool {
final String name;
final double weight;
public Tool(String name, double weight) {
this.name = name;
this.weight = weight;
}
}
public class Drawer {
final String name;
final List<Tool> tools;
public Drawer(String name) {
this.name = name;
this.tools = new ArrayList<>();
}
}
public class Toolbox {
final String name;
final List<Drawer> drawers;
public Toolbox(String name) {
this.name = name;
this.drawers = new ArrayList<>();
}
public void addDrawers(String... names) {
for (String name : names) {
drawers.add(new Drawer(name));
}
}
}
Now you can do
String[] drawers = {"Screwdrivers", "Files", "Spanners"};
Toolbox toolbox = new Toolbox("My toolbox");
toolbox.addDrawers(drawers);
Or just
Toolbox toolbox = new Toolbox("My toolbox");
toolbox.addDrawers("Screwdrivers", "Files", "Spanners");

I'm getting null pointer issues.
In myObject.callAMethod(aParameter); check myObject is not null.
Also refer to What is a NullPointerException, and how do I fix it?
What's the proper way to instantiate everything if I want to
instantiate a toolbox?
Each class can have it's own file. If you are starting with java I would go this way. There are ways to put everything in the same file, but you'll get to that in time.
The propper way to instantiate as in which order, what makes sense is from the bottom up. First Tool, then Drawer, then ToolBox. In this way the encolosed element already exists when you create the enclosing object.
do I need to use the import statement
Depends in which package you create the different classes. The IDE will highlight if you need to import the class.
I've read an entire book on programming Java on Android and it doesn't
cover the questions I asked.
This cannot be true.

Related

Instantiating Objects in Java

I asked a similar question to this recently, but I did a bad job at explaining it, so I am going to try again.
I cannot figure this out for the life of me. I have to do two different java files for this programming assignment, and when running the program from command prompt I get an error that says it cannot find symbol of when I create my object in the second class, and when I run the code in Eclipse I get the error "Error occurred during initialization of boot layer
java.lang.LayerInstantiationException: Package jdk.internal.jrtfs in both module jrt.fs and module java.base".
I even copied an example straight from the textbook to understand it, but it isn't working even though I have exactly what's in the textbook. The pastebin links are for the two classes that come from the textbook examples.
Please someone tell me what's wrong here.
First class: https://pastebin.com/KYHtDHPt
public class Account {
private String name;
public Account(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Second class: https://pastebin.com/ADUsjjaR
public class AccountTest {
public static void main(String[] args) {
Account account1 = new Account("Brandon Williams");
System.out.printf("Account one is: %s%n",account1.getName());
}
}

I seem to be getting the error Duplicate class in a java class [duplicate]

This question already has answers here:
java - duplicate class
(6 answers)
Closed 4 years ago.
I am getting an error that says "duplicate class: (package name).(class name)"
This is the code the line that says the error is "public class Enemy"
package rpgdemo;
public class Enemy {
String name;
int weaponId;
int baseAtk;
int baseDef;
int hitRate;
int hp;
public Enemy(String name,int weaponId, int baseAtk,int baseDef,int hitRate,int hp){
this.name = name;
this.weaponId = weaponId;
this.hp = hp;
this.baseAtk = baseAtk;
this.baseDef = baseDef;
this.hitRate = hitRate;
}
}
The problem is that you have another class containing tha same class name. Maybe you have deleted the java file before but the class file still remains. So I suggest you clean and build the project.
If you do not have same class in the package, try clearing the cache of the editor otherwise change class name. Check this java - duplicate class

Getting String Array in Android from .xml using Resources.getSystem()

I am trying to convert string-array from strings.xml to array in Java class
(the model part of MVC), there-for I cannot use getResources().getStringArray(R.array.array_name);
(it works only in Android components such as activity, fragment and so on).
So I can use only Resources.getSystem().getStringArray(R.array.array_name);
but When I try to run it in the emulator, I get an exception.
I found similar questions that referred that problem here. but I didn't understand the solution.
Here my exception:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.danirg10000gmail.therpiststep1/com.danirg10000gmail.therpiststep1.MainActivity}: android.content.res.Resources$NotFoundException: String array resource ID #0x7f0b0000
(My exception is same as in the link above.)
In my code I have two classes one class represents questions, another class have a list of questions objects.
Here is my code:
public class QuestionM {
private String mQuestion;
private String mAnswer;
private String mExplanation;
//constructor
public QuestionM(String question,String explanation) {
mQuestion = question;
mExplanation = explanation;
}
public class QuestionnaireM {
private List<QuestionM> mQuestionsList;
//constructor
public QuestionnaireM(){
mQuestionsList = new ArrayList<>();
Resources resources = Resources.getSystem();
//when i creating object of that class android points the crush here
String [] questions = resources.getStringArray(R.array.test);
String [] questionExplanations = resources.getStringArray(R.array.test_a);
for (int i=0; i<questions.length; i++){
QuestionM question = new QuestionM(questions[i],questionExplanations[i]);
mQuestionsList.add(question);
}
}
also I didn't quite understand the difference between system-level resources, and application-level resources, I search it in androidDevelopers and in Google but not found any good explanation. can somebody please explain that?
One suggestion, not sure if it will work. But you can try and let me know. Why not get the context in QuestionM constructor and initialize your class level context variable with the received context. Now use this context to
mContext.getResources().getStringArray(R.array.array_name);
public class QuestionM {
private String mQuestion;
private String mAnswer;
private String mExplanation;
private Context mContext;
//constructor
public QuestionM(String question,String explanation, Context context) {
mQuestion = question;
mExplanation = explanation;
mContext = context;
}
public class QuestionnaireM {
private List<QuestionM> mQuestionsList;
//constructor
public QuestionnaireM(){
mQuestionsList = new ArrayList<>();
//when i creating object of that class android points the crush here
String [] questions = mContext.getResources().getStringArray(R.array.test);
String [] questionExplanations = mContext.getResources().getStringArray(R.array.test_a);
for (int i=0; i<questions.length; i++){
QuestionM question = new QuestionM(questions[i],questionExplanations[i]);
mQuestionsList.add(question);
}
}
According to the docs getSystem() does this:
Return a global shared Resources object that provides access to only
system resources (no application resources), and is not configured for
the current screen (can not use dimension units, does not change based
on orientation, etc).
Therefore calling getStringArray() with the resource Id R.array.test is totally useless since the id referenced is that of an Application resource.
If you want to load the contents of R.array.test, use getStringArray() from getResources().
You can pass a parameter of type Resources to the constructor or String[]. i.e. :
public QuestionnaireM(Resources resource) {
// stuffs
}

Android: Custom Parcelable Class Crashes App Without Throwing Exception

I've got an Android app with custom objects which implement the Parcelable interface. They way I have it set it up is that my program initially creates an ArrayList of a custom class Products from a file in the bundle. I can see and confirm that the arraylist and it's instance variabels are populated appropriately. This class has several instance variables along with one being another ArrayList but with the String class. Remember that fact.
I am trying to pass the ArrayList<Product> into a new activity like so:
try {
Intent i = new Intent(RootActivity.this, ProductsActivity.class); //Intent from this activity to the next
i.putParcelableArrayListExtra("Products", app_products); //Puts my ArrayList<Class A> as an extra
startActivity(i); //Launch the activity
}
catch(Exception e){
Log.d("Activity Error", "Error Here:" + e.getMessage());
}
I am collecting the information back from the intent in my new activity by pulling the ArrayList out by using
app_products = getIntent().getParcelableArrayListExtra("Products");
For my custom class, it looks something like this, along with the implemented Parcelable methods.
public class Product implements Parcelable{
private String name;
private String cost;
private ArrayList<String> similarItems;
public Product{
name = null;
cost = null;
similarItems = new ArrayList<String>();
}
public Product(String name, String cost){
this();
this.name = name;
this.cost = cost;
}
public addSimilarItem(String item){
similarItems.add(item);
}
public static final Parcelable.Creator<Product> CREATOR
= new Parcelable.Creator<Product>()
{
public Product createFromParcel(Parcel in) {
return new Product(in);
}
public Product[] newArray(int size) {
return new Product[size];
}
};
public int describeContents(){
return 0;
}
private Product(Parcel in){
name = in.readString();
cost = in.readString();
similarItems = in.readArrayList(String.class.getClassLoader());
}
public void writeToParcel(Parcel out, int flags){
out.writeString(name);
out.writeString(cost);
out.writeList(similarItems);
}
}
So this works well WITHOUT my String arraylist being added in the class
Comment out out.writeList(similarItems); and also similarItems = in.readArrayList(String.class.getClassLoader());
but once you add them back in into the class, the app crashes but it doesn't even throw a message for debugging. I've wrapped everything around try-catch statements and android doesn't even report the app crashed with the normal dialog on the springboard. I am truly at a loss.
It is worth mentioning that I've used some log statements to understand where the program is crashing despite the fact that android wont throw an exception. I can see that all of the items in my ArrayList undergoes the writeToParcelMethod and completes writing. The Product(Parcel in) method is never called. Lastly, I can also see the class I am launching the new activity from enters the Pause State and my new Activity is never created.
Let me know if I can provide any additional information.
Fairly certain your problem is the use of writeList(). writeList() seems to indicate that it follows the same contract as writeValue() for the items contained in the list. readList() however, seems to indicate that the values must be Parcelable (which String is not).
Either way, typically these calls have to be very specifically linked to their inverse (e.g. writeString() must be read in with readString(), not readValue()) so you should instead use the provided methods for reading/writing String Lists:
// Takes in a List<String> which may be null
out.writeStringList(similarItems);
// Returns either null or a new ArrayList<String> with the contents
similarItems = in.createStringArrayList();
These seemed to be due to some malformed XML which my app uses as a resource. Not sure why this was this issue but after many hours of hunting it down, I was able to remove the bad XML and will revisit this issue at a later date towards when I need to release the app.
Right now, I'm just gonna worry about continuing to develop it. I'll try to remember to check back here if I find anything interesting about my XML.

How to pass a custom class between Activities

I found many simple solutions to this (such as Intent.putExtra(String, String) and Bundle.putString(String, String)), but this is not helpful for my situation.
I have a class called MyMP3 which contains non-primitive types. I need to pass the following for MyMP3...
private AudioFile audioFile;
private Tag tag;
private int index;
private boolean saved, startedWithLyrics;
private String id3lyrics;
AudioFile and Tag are both classes that I imported from a .jar file. How can I go about passing these to another Activity via Intents? I tried messing with implementing Parcelable for my "MyMP3" class, but I am not sure how to correctly use these methods when not passing primitive types.
Could you help me out and look at my code below and try to tell me how to correctly use Parcelable with a custom class like mine? How do I set the Parcel in the writeToParcel function and how do I correctly retrieve the class in another Activity?
Below is my code (the part that is important, at least). I've been trying different things for a couple of days now, but I cannot get it to work. Please help me out!
public class MyMP3 extends AudioFile implements Parcelable
{
private AudioFile audioFile;
private Tag tag;
private int index;
private boolean saved, startedWithLyrics;
private String id3lyrics;
public MyMP3(File f, int index)
{
this.audioFile = AudioFileIO.read(f);
this.tag = this.audioFile.getTag();
this.index = index;
this.saved = false;
this.id3lyrics = getLyrics();
}
#Override
public int describeContents()
{
return 0;
}
#Override
public void writeToParcel(Parcel out, int flats)
{
/* This method does not work, but I do not know how else to implement it */
Object objects[] = {this.audioFile, this.tag, this.index, this.saved, this.startedWithLyrics, this.id3lyrics};
out.writeArray(objects);
}
public static final Parcelable.Creator<MyMP3> CREATOR = new Parcelable.Creator<MyMP3>()
{
public MyMP3 createFromParcel(Parcel in)
{
/* Taken from the Android Developer website */
return new MyMP3(in);
}
public MyMP3[] newArray(int size)
{
/* Taken from the Android Developer website */
return new MyMP3[size];
}
};
private MyMP3(Parcel in)
{
/* This method probable needs changed as well */
Object objects[] = in.readArray(MyMP3.class.getClassLoader());
}
}
You can make your MyMP3 class Parcelable like that. Make sure you get the read/write order correct. The non-primitives must also be Parcelable, so you might not have control over that unfortunately. Alternatively, you could come up with your own serialization/deserialization. You could use a text format, like JSON or XML. Another alternative is to use subclass Application (make sure you declare it in your manifest) and use it is as a place to hang objects that span Activities. This keeps the object in memory for the lifecycle of your app, so be careful with doing this.

Categories