This question already has answers here:
What does the 'static' keyword do in a class?
(22 answers)
Closed 3 years ago.
Can someone explain how the below code works without any exceptions. I am thinking when new instance is created for SUNDAY it creates a new instance for MONDAY (inside SUNDAY) too and then SUNDAY again (inside MONDAY) and so on... Something like recursive as they both are part of the class Week. But my understanding is wrong because the below code is working fine.
public class Week {
public static final Week SUNDAY = new Week("SUNDAY",0);
public static final Week MONDAY = new Week("MONDAY",1);
private String name;
private int val;
private Week(String name, int val) {
this.name = name;
this.val = val;
}
public int getIndex() {
return this.val;
}
#Override
public String toString() {
return this.name;
}
}
I got this doubt when I was reading about java enums.
You will see the mentioned behavior when SUNDAY and MONDAY are instance variables (non-static).
Since you have declared them as static those are the properties of the class and initialized when the Week class is loaded one after another. One object creation SUNDAY would not contain MONDAY in it and vice versa.
As I mentioned in the beginning, the below code won't run successfully as it will try to create instances recursively without an end.
public class Week {
public final Week SUNDAY = new Week("SUNDAY",0);
public final Week MONDAY = new Week("MONDAY",1);
private String name;
private int val;
private Week(String name, int val) {
this.name = name;
this.val = val;
}
public int getIndex() {
return this.val;
}
#Override
public String toString() {
return this.name;
}
public static void main(String[] args) {
new Week("TUESDAY", 2);
}
}
SUNDAY and MONDAY are static variables. Which means that they are class variables. Object of class Week will not have properties called SUNDAY and MONDAY
You can get more information regarding static here: What does the 'static' keyword do in a class?
Related
So I have this assignment which I need to put data into a tree set. I have three classes they are :
Brother.java. The assignment said the constructor is not public, so I'm using the getInstance() to initialize Brother object
public class Brother {
String name;
int day;
int month;
private static Brother instance = null;
private Brother()
{
name = "0";
day = 0;
month = 0;
}
public static Brother getInstance()
{
if(instance == null)
{
instance = new Brother();
}
return instance;
}
}
Family class. This class is used to assign the brother object into the tree set with Brother as the objects.
import java.util.Set;
import java.util.TreeSet;
public class Family {
Set<Brother> Brothers;
public Family()
{
this.Brothers = new TreeSet<Brother>();
}
public Brother makeBrother()
{
Brother B = Brother.getInstance();
return B;
}
public boolean addBrother(String name, int day, int month)
{
Brother B = Brother.getInstance();
return Brothers.add(B);
}
}
And finally the main class
public class Main {
public static void main(String[] args) {
Family myFamily = new Family();
myFamily.makeBrother();
// myFamily.addBrother("Shane", 3, 2);
}
}
whenever I try to use myFamily.addBrother() I always got this error "Exception in thread "main" java.lang.ClassCastException: class Brother cannot be cast to class java.lang.Comparable (Brother is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')". What do I have to do with that? The program is perfectly fine when I use myFamily.makeBrother(). This algorithm is not all done yet but when I try to run it this happened to me and I cannot continue to the next step. Thank you before.
You are using a Set instead of a List because you want to avoid duplicates. To know which Brothers are duplicate, a TreeSet needs either a comparator, or the objects themselves need to implement Comparable.
Read the javadoc of TreeSet for more: https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html
BTW that getInstance always returns the same instance. You'll probably need to change that to createInstance or something that actually creates new ones.
I agree with #GreyFairer, you have to provide a comparator in order to use Set, see this example:
Class Cast Exception problems with TreeSet
I hope it can helps you!
I see a few problems there.
You have defined Brother as a singleton. That means only one Brother instance will exist in your program. So all references to Brother will point to the same instace. I would avoid singleton for this class since doesn't makes sense.
If you what to use a TreeSet (without providing a Comparator for the Tree) then Brother must implement Comparable
Family.makeBrother just return the singleton Brother, but does not add it to the family tree, that's why you don't get the error.
This is a working rework of your code
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class FamilyTreeSet {
public static void main(String[] args) {
Family myFamily = new Family();
myFamily.addBrother("Shane", 3, 2);
myFamily.addBrother("Bob", 2, 4);
System.out.println(myFamily);
}
public static class Brother implements Comparable<Brother>{
private String name;
private int day;
private int month;
public Brother(String name, int day, int month) {
this.name = name;
this.day = day;
this.month = month;
}
public String getName() {
return name;
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
#Override
public int compareTo(Brother o) {
return Comparator.comparing(Brother::getName, String.CASE_INSENSITIVE_ORDER).compare(this, o);
}
#Override
public String toString() {
return "Brother{" +
"name='" + name + '\'' +
", day=" + day +
", month=" + month +
'}';
}
}
public static class Family {
Set<Brother> Brothers;
public Family()
{
this.Brothers = new TreeSet<Brother>();
}
public boolean addBrother(String name, int day, int month)
{
Brother B = new Brother(name, day, month);
return Brothers.add(B);
}
#Override
public String toString() {
return "Family{" +
"Brothers=" + Brothers +
'}';
}
}
}
I'm using the each brother's name to compare brothers. Check that I first add Shane but in the output Bob goes first. If you want to compare brothers by birthday just change the compareTo.
Family{Brothers=[Brother{name='Bod', day=2, month=4}, Brother{name='Shane', day=3, month=2}]}
This question already has answers here:
C# vs Java Enum (for those new to C#)
(13 answers)
Is it possible to add custom properties to c# enum object?
(2 answers)
Closed 2 years ago.
I have a very basic question. In Java, it is possible to point attributes and variables to Enums, such as:
public enum DayTime{
Morning("Morning"),
Afternoon("Afternoon"),
Night("Night");
private string description;
Daytime(string description){
this.description = description;
}
public string getDescription(){
return description;
}
}
Is it possible to apply the same concept to C#? I am trying to get modular descriptions to products, whereas their name, contents and characteristics would be shown in a string of text, and Enums looked like the best alternative to modify this text according to which characteristic is selected.
C# enums are very basic compared to Java enums. If you want to simulate the same kind of behavior you need to use a class with an inner enum:
using System.Collections.Generic;
public sealed class DayTime
{
public static readonly DayTime Morning = new DayTime("Morning", InnerEnum.Morning);
public static readonly DayTime Afternoon = new DayTime("Afternoon", InnerEnum.Afternoon);
public static readonly DayTime Night = new DayTime("Night", InnerEnum.Night);
private static readonly List<DayTime> valueList = new List<DayTime>();
static DayTime()
{
valueList.Add(Morning);
valueList.Add(Afternoon);
valueList.Add(Night);
}
//the inner enum needs to be public for use in 'switch' blocks:
public enum InnerEnum
{
Morning,
Afternoon,
Night
}
public readonly InnerEnum innerEnumValue;
private readonly string nameValue;
private readonly int ordinalValue;
private static int nextOrdinal = 0;
private string description;
internal DayTime(string name, InnerEnum innerEnum)
{
this.description = name;
nameValue = name;
ordinalValue = nextOrdinal++;
innerEnumValue = innerEnum;
}
public string Description
{
get
{
return description;
}
}
//the following methods reproduce Java built-in enum functionality:
public static DayTime[] values()
{
return valueList.ToArray();
}
public int ordinal()
{
return ordinalValue;
}
public override string ToString()
{
return nameValue;
}
public static DayTime valueOf(string name)
{
foreach (DayTime enumInstance in DayTime.valueList)
{
if (enumInstance.nameValue == name)
{
return enumInstance;
}
}
throw new System.ArgumentException(name);
}
}
Given this complexity, it may be best to rewrite your logic in a way that's more natural for C# without using enums.
Here is the exact instruction on what my professor has asked me to do:
Write a constructor with two parameters for int year and String player.
Use internal method call to setDetails to initialize the fields.
I have the class so far like this:
public class Card
{
private int year;
private String player;
public Card(String player, int year)
{
}
}
Not sure what the internal method call is, I have looked on the internet and StackOverflow and have not found anything that has benefited me. Any help is appreciated.
Thank you,
A first year programming student.
You need a method to set the details of the card, like this:
private final void setDetails(int year, String player) {
this.year = year;
this.player = player;
}
And then in the constructor, you can call setDetails(year, player).
Based on your statement here is the code that you 're asking for:
public class Card {
private int year;
private String player;
public Card(String player, int year) {
setDetails(player,year);
}
/*i'm making it public in case you want to call the setter directly
somewhere and final since i call an overridable method in the constructor*/
public final void setDetails(String player,int year) {
this.player=player;
this.year=year;
}
}
This question already has answers here:
Setter methods or constructors
(10 answers)
Why use getters and setters/accessors?
(37 answers)
Closed 6 years ago.
In the below code I've already declared that room = r; subject = s; and time = t; in the user defined constructor, so why is it necessary to do so again in set methods, my lecturer specifically asked that we add set methods for the room subject and time but it's redundant code as when I comment it out it still works. Do you only need to include set methods when there is no used defined constructor? What could be the advantage of having them set methods there?
class LectureTest{
public static void main (String [] args){
Lecture l1 = new Lecture(140, "Comp", 5);
l1.display();
Lecture l2 = new Lecture(280, "Sports", 3);
l2.display();
Lecture l3 = new Lecture(101, "Business", 5);
l3.display();
Lecture l4 = new Lecture(360, "Shooting", 4);
l4.display();
Lecture l5 = new Lecture();
l5.display();
}
}//end of LectureTest
class Lecture{
private int room;
private String subject;
private int time;
Lecture(int r, String s, int t){
room = r;
subject = s;
time = t;
}
Lecture(){}
public void setroomNumber(int r){
room = r;
}
public void setSubject(String s){
subject = s;
}
public void setTime(int t){
time = t;
}
public int getroomNumber(){
return room;
}
public String getSubject(){
return subject;
}
public int getTime(){
return time;
}
public void display(){
System.out.printf("\n" + "Room Number: " + getroomNumber() + "\n" + "Subject: " + getSubject() + "\n" + "Time " + getTime() + "\n");
}
}
The constructor "initializes" your values.
Let's say you have...
public class Person {
public String name;
public int age;
public Person (String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
String str;
str = "My name is "+name+" and I am "+age+" years old!";
return str;
}
}//End of Person
public class Main {
public static void main(String [] args) {
Person person = new Person("Bob", 15);
System.out.println(person.toString());
System.out.println("Switching my name...");
person.setName("Joe");
System.out.println(person.toString());
}
}//End of main
You see the difference? You should use the constructor if you want to create a new instance of the object. This way, you can set all the fields of the object at once and not need to call 490832490 setters (in this case, one for name and one for age...). You then can use the setter approach when you want to change the value of a field, PRIOR TO the object been created.
I DID ALL THIS ON THIS FORUM SO I MIGHT HAVE SYNTAX ERRORS SO CAREFUL...DIDN'T USE AN IDE IF YOU WANT TO TEST IT
The set methods make your object mutable. If you don't have the set methods and your variables are private then the Object will be immutable. You won't be able to change the values after it is constructed...If the values need to change you would have to create a new Object.
"Setters" allow you to modify private attributes of your object after instantiating. For example:
Lecture l1 = new Lecture(140, "Comp", 5);
//Since "room" is private you can't write l1.room = 4
//and have to use the setter method instead:
l1.setroomNumber(4);
l1.display();
They are also very useful if you want to do something if an attribute changes.
Let's assume you are using Observers, then you could call notifyObservers() or setChanged() in your setter method and never have to worry about these methods not getting called if your attribute changes.
This is a question from an exam past paper. I have completed the question and it works. However, i feel my implementation may be weak e.g. my use of static throughout the Gregorian class.
I was given three methods to write in any way i saw fit (in the Gregorian class) given a scenario for each. Was I right in using static on the three methods in the Gregorian class.
Also the day, month and year fields are meant to be immutable, is setting them as private enough? (once they are created the field values cannot be changed)
public class Date {
private int day;// needs to be immutable?
private String month;// needs to be immutable?
private int year;// needs to be immutable?
public Date(int theDay, String theMonth, int theYear) {
this.day = theDay;
this.month = theMonth;
this.year = theYear;
}
public int getDay() {
return day;
}
public String getMonth() {
return month;
}
public int getYear() {
return year;
}
}
public class Gregorian {
public static Date d;
public static boolean leapYear(){
if(d.getYear() %400==0 || (d.getYear()%4==0 && d.getYear()%100!=0)){
return true;
}else{
return false;
}
}
public static int getGregorianDateNumber(){
int a = (d.getYear()*384)*(32+d.getDay());
return a;
}
public static int getISO8601Date(){
int b = (d.getYear()*367)+d.getDay();
return b;
}
public static void main (String[] args){
d = new Date(9, "June", 8);
System.out.println(getGregorianDateNumber());
System.out.println(getISO8601Date());
System.out.println(leapYear());
}
}
Instead of the static methods and the static field d make them all non-static.
public class Gregorian {
private final Date d;
public Gregorian(Date d_) {
this.d = d_;
}
public boolean isLeapyear() {
... // implemented as above
}
... // Other methods as above, but all non-static.
}
And main as follows:
public static void main (String[] args){
Date d = new Date(9, "June", 8);
Gregorian g = new Gregorian(d);
System.out.println(g.getGregorianDateNumber());
System.out.println(g.getISO8601Date());
System.out.println(g.leapYear());
}
Strings are by default immutable.
private int day;// needs to be immutable?
private int year;// needs to
are not immutable fields as you defined. Their state can change. Make them final.
NOTE: Making a reference final doesn't mean object state can't be changed (In your case this note is irrelevant, because you are not referencing objects).
I'll agree with thinksteep - adding "final" to your fields will help keep them from being changed. Not having setters reinforces this.
In addition, I want to point out that
private String month;// needs to be immutable?
can be created as anything, from "January" to "Pie". If I may suggest, change it to an enum and establish the allowed values for months.
public enum MonthName {
JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC;
}
Change your Date class to the following:
private final int day;
private final MonthName month;
private final int year;
public Date(int theDay, MonthName theMonth, int theYear) {
this.day = theDay;
this.month = theMonth;
this.year = theYear;
}
both day and year are primitives and There is already immutable version of int available which is Integer you can make use of that.
Second thing is, rather having a static reference to Date in Gregorian, pass the Date as an argument to each of the static methods. You can assure the thread safety then.