简体   繁体   中英

Take a value from a list through a getter method?

I have 3 classes, Human, Date, and Zodiac. In Date I have two int types, month and day. I have normal constructor and getter. In Human I have a String name and a birthday from the type Date.

My Class Date:

public class Date {
    private int month;
    private int day;
    
    public Date(int month, int day) {
        this.month = month;
        this.day = day;
    }
    public int getMonth() { return month;}

    public int getDay() {return day;}

My Class Human

public class Human {
    private String name;
    private Date birthday;

    public Human(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

   public String getName() { return name;}
   
   public BirthDate getBirthday() { return birthday;}

In My class Zodiac I have a Main where I created some objects. Then I have a method zodiacToHuman were I give a Human his star sign. But this method didn't work at all. The method has a List as Parameter and returns a Map.

My method in class Zodiac:

public static Map<Human, String> zodiacToHuman(List<Human> humanlist){
     Map<Human, String> personSign = new HashMap<>();
     Human human;
     String sign = "";
     int day = Date.getDay();
     int month = Date.getMonth();
     if (month == 1) {
            if (day < 20)
                sign = "capricornus";
                humanSign.put(human, sign);
            else
                sign = "aquarius";
                humanSign.put(human, sign);
     }//and so on
}

This is the error I get:

Non-static method 'getDay()' cannot be referenced from a static context

Non-static method 'getMonth()' cannot be referenced from a static context

Variable Human might not have been initialized

Can someone help me?

You can't do int day = Date.getDay()

Create an object first of the Date class and use it to get the day and month

Data date = new Date()
int day = date.getDay()
int month = date.getMonth()

Also you haven't initialised your Human class object. You can write

Human human = new Human(some_day, some_month)

As I understand the humanList contains entries of Human Objects. You should try iterating over the list, like so

public static Map<Human, String> zodiacToHuman(List<Human> humanlist) {
     Map<Human, String> personSign = new HashMap<>();
     for (Human human : humanList) {
       String sign = "";
       int day = human.getBirthday().getDay();
       int month = human.getBirthday().getMonth();
       if (month == 1) {
            if (day < 20) {
                sign = "capricornus";
            } else {
                sign = "aquarius";
            }
       }  //and so on

       humanSign.put(human, sign);
    }
}

Let's change the name of Date to more precise MonthWithDay .

We can shorten the code of that class by making it a record . By default, the implicitly created getter methods are named the same as the member field name.

public record MonthWithDay( int month , int day ) { }

Similarly we can define your Human class as a record in one short line.

public record Human( String name , MonthWithDay monthDayWhenBorn ) { }

Regarding your method to determine zodiac:

public static Map<Human, String> zodiacToHuman(List<Human> humanlist){ …

… there is no need for static . In your scenario, that seems like a reasonable feature on your Human class.

Tip: In object-oriented programming, using static is not object-oriented. Try to minimize use of static . Use as a last resort only.

public record Human( String name , MonthWithDay monthDayWhenBorn )
{
    public String zodiac ( )
    {
        int day = this.monthDayWhenBorn.day();
        int month = this.monthDayWhenBorn.month();
        if ( month == 1 )
        {
            if ( day < 20 )
            { return "capricornus"; }
            else
            { return "aquarius"; }
        }
        return "other";
    }
}

Populate some example data.

List < Human > humans =
        List.of(
                new Human( "Alice" , new MonthWithDay( 1 , 11 ) ) ,
                new Human( "Alice" , new MonthWithDay( 1 , 22 ) ) ,
                new Human( "Carol" , new MonthWithDay( 11 , 27 ) )
        );

Create your map of human to zodiac.

Map< Human , String > mapOfHumanToZodiac = new HashMap<>() ;

Loop through each Human object, interrogate for its zodiac, and place into our map.

for ( Human human : humans )
{
    mapOfHumanToZodiac.put( human , human.zodiac() );
}

Dump to console.

System.out.println( "mapOfHumanToZodiac = " + mapOfHumanToZodiac );

mapOfHumanToZodiac = {Human[name=Alice, monthDayWhenBorn=MonthWithDay[month=1, day=11]]=capricornus, Human[name=Alice, monthDayWhenBorn=MonthWithDay[month=1, day=22]]=aquarius, Human[name=Carol, monthDayWhenBorn=MonthWithDay[month=11, day=27]]=other}

By the way, in real work we would define an enum to represent each of the zodiac signs rather than use mere strings. Doing so provides type-safety , ensures valid values (avoids errors from typos in the strings), and makes the code more self-documenting .

java.time

Java comes with an industry-leading framework of date-time classes, found in the java.time package. These classes include a MonthDay class. So no need to invent your own. We can delete your MonthWithDay class.

Tweak the Human class.

public record Human( String name , MonthDay monthDayWhenBorn )  // <-- Use java.time.MonthDay class.
{
    public String zodiac ( )
    {
        int day = this.monthDayWhenBorn.getDayOfMonth();        // <-- Use java.time.MonthDay class.
        int month = this.monthDayWhenBorn.getMonthValue();      // <-- Use java.time.MonthDay class.
        if ( month == 1 )
        {
            if ( day < 20 )
            { return "capricornus"; }
            else
            { return "aquarius"; }
        }
        return "other";
    }
}

Change how we create the sample data.

List < Human > humans =
        List.of(
                new Human( "Alice" , MonthDay.of( 1 , 11 ) ) ,  // <-- Use java.time.MonthDay class.
                new Human( "Alice" , MonthDay.of( 1 , 22 ) ) ,
                new Human( "Carol" , MonthDay.of( 11 , 27 ) )
        );

And we get the same results.

Errors and reasons

Variable Human might not have been initialized

Its not a error its a warning that saying human variable might be null as you have only decalre the variable human . To initialize either you need to create an instance or assign null to it

Human human = new Human(YOUR VALUES);
//or 
Human human = null;

Non-static method 'getDay()' cannot be referenced from a static context

Non-static method 'getMonth()' cannot be referenced from a static context

You cannot access public methods of a class directly without creating an object.

NOTE

As per my understanding you are giving each human a sign value.You can achive the same while you are creating each human object and later on create a map from it. Eg:

public class Human {
    private String name;
    private Date birthday;
    private String sign;

    public Human(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
        assignZodiac();
    }   

    private void assignZodiac(){
        String sign = "";

        //getting birhday month and day values
        int day = birthday.getDay();
        int month = birthday.getMonth(); 

    // your logic of assignment
        if (month == 1) {
                    if (day < 20)
                        sign = "capricornus";
                    else
                        sign = "aquarius";
            }//and so on

    }

//getter setter

}

Now you can create a map from the list. eg:

    // human list has been already created
    Map<Human,String> humanSign=newHasmap<>();    
    for(Human human : humanList) {
        humanSign.put(human,human.getSign()) //asuming getSign is the getter for sign filed in Human.
    }

Also I would suggest you to change Date class name to something else since java already has a class of the same name. It's just for naming convection

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