简体   繁体   中英

How do you format arrays to hold objects?

Im new to java and I am super confused on how you format arrays to hold objects, specifically with multiple data types. I am trying to make an array called myMonsters that essentially holds a bunch of other monsters, which is a string and an integer. 1, I really don't understand how to put objects into an array. 2, I don't get why the array are under one class name instead of another. What I mean -->

private Monster[] myMonsters;
    private int s;
    public Monsters(int size)
    {
        s = size;
        myMonsters = new Monster[s];
    }
    public void add(int spot, Monsters m)
    {
        myMonsters[spot] = m;
    }

This creates the array that holds the monster objects. I don't understand why I would create the array under Monster. Doesn't it make more sense to create it under the Monsters class, where the monster objects are being held?

private int weight;
    private int height;
    private int age;
    public Monster( int a, int h, int w )
    {
        age = a;
        height = h;
        weight = w;
    }

And of course this creates the objects. I can tell how poorly formatted this questions is but can you still help me with this?

A class is a template, like a cookie-cutter for making cookies. A class has no content, just as a cookie-cutter has no cookie dough.

A cookie-cutter exists only to make delicious cookies. A class exists only to make useful objects (aka instances). Objects have content inside, just as cookies have dough inside.

Monster is the class, the cookie-cutter, for making various monster objects.

In Java 16 and later, we can more briefly define a class as a record . The compiler implicitly creates the constructor, getters, equals & hashCode , and toString .

package work.basil.example.animalkingdom.cookies;

public record Monster(String name , int weight)
{
}

As a conventional class, that would be:

package work.basil.example.animalkingdom.cookies;

import java.util.Objects;

public final class Monster
{
    private final String name;
    private final int weight;

    public Monster ( String name , int weight )
    {
        this.name = name;
        this.weight = weight;
    }

    public String name ( ) { return name; }

    public int weight ( ) { return weight; }

    @Override
    public boolean equals ( Object obj )
    {
        if ( obj == this ) return true;
        if ( obj == null || obj.getClass() != this.getClass() ) return false;
        var that = ( Monster ) obj;
        return Objects.equals( this.name , that.name ) &&
                this.weight == that.weight;
    }

    @Override
    public int hashCode ( )
    {
        return Objects.hash( name , weight );
    }

    @Override
    public String toString ( )
    {
        return "Monster[" +
                "name=" + name + ", " +
                "weight=" + weight + ']';
    }
}

Let's cut some cookies using that cookie-cutter. We want to represent 3 monsters, each with a different name and different weight.

Monster x = new Monster( "Alice" , 42 );
Monster y = new Monster( "Bob" , 77 );
Monster z = new Monster( "Carol" , 58 );

There we have three separate objects, each cut from the same Monster class. We are currently handling the 3 monsters separately, each assigned to separate variables.

If we want to track those monsters together, in a particular order, we do not need your Monsters class. Just use an array.

Say we want them organized together by weight.

Monster[] monstersByWeight = new Monster[ 3 ];
monstersByWeight[ 0 ] = x;
monstersByWeight[ 1 ] = z;
monstersByWeight[ 2 ] = y;

The Monster[] says we want this variable named monstersByWeight to hold an array that holds Monster objects. The new Monster[ 3 ] creates such an array, an array with three empty slots. The = puts that array of three empty slots into the variable named monstersByWeight so we can use it later.

Dump that array to the console, to inspect.

String output = Arrays.toString( monstersByWeight );
System.out.println( "output = " + output );

output = [Monster[name=Alice, weight=42], Monster[name=Carol, weight=58], Monster[name=Bob, weight=77]]

You said:

… to hold objects, specifically with multiple data types

There is only one data type involved here: Monster . We have only Monster objects to track. So the data type of the array named monstersByWeight is Monster .

If we want to add another Monster object:

Monster david = new Monster( "David" , 63 ) ;

…to our array, we need to open up a slot. Using arrays, this is tedious programming. Likely we would create another array, move elements from old array to new array while skipping the slot we want to keep open for our new Monster . Not fun writing that code.

Fortunately, that code has already been written. We can use the class ArrayList . This class implementing the List interface. ArrayList can do all the element-insertion work for us.

List< Monster > monstersByWeight = new ArrayList<>() ;

The List< Monster > monstersByWeight says we want a list that holds Monster objects. The new ArrayList<>() instantiates such a list, of a default size.

Next we add our Monster objects.

monstersByWeight.add( x ) ;
monstersByWeight.add( z ) ;
monstersByWeight.add( y ) ;

Dump to console.

System.out.println( monstersByWeight ) ;

[Monster[name=Alice, weight=42], Monster[name=Carol, weight=58], Monster[name=Bob, weight=77]]

Later we can insert our new Monster object named David , assigned to variable named david . At weight of 63, this new monster belongs before the one named Bob but after the one named Carol . Like arrays, the List interface uses annoying zero-based counting rather than ordinal counting. To specify the 3rd element, we say 2 (annoying, as I said).

monstersByWeight.add( 2 , david ) ;

Dump to console.

System.out.println( monstersByWeight ) ;

[Monster[name=Alice, weight=42], Monster[name=Carol, weight=58], Monster[name=David, weight=63], Monster[name=Bob, weight=77]]

You asked:

This creates the array that holds the monster objects. I don't understand why I would create the array under Monster. Doesn't it make more sense to create it under the Monsters class, where the monster objects are being held?

No, you would not want a collection of Monster objects stored within the class of Monster . The job of the Monster class is to define the state (data) and behavior (methods) for any one Monster object (instance) that represents any one real-world monster.

You want a separate class to track a bunch of Monster objects together. Here in this Answer we used an instance of the ArrayList class which we named monstersByWeight to track our group of monsters. You could just as well have written your own MonsterList class if you wanted to do all that array-rearranging yourself, as practice. But for real work, use ArrayList .

The principal at work here is called separation of concerns . The ArrayList class knows nothing of what it means to be a Monster . And the Monster class knows nothing of how to group together Monster objects. Following this principal leads to clean, well-organized code that is easier to read, comprehend, and maintain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM