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?
CodePudding user response:
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)
CodePudding user response:
As I understand the humanList contains entries of Human Objects. You should try itterating 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);
}
}
CodePudding user response:
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.
CodePudding user response:
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