Creating an array object from a constructor in Java - java

Is this correct? I am speaking about the this.rates part, and the return.rates part. Trying to construct and array object from a constructor, and return number of array objects in a collection. I am still learning, so forgive me if my terminology is a bit off.
public class ArrayFun
{
// instance variables
private ArrayList<ArrayRates> rates;
/**
* Constructor for objects of class ArrayFun.
*/
public ArrayFun()
{
this.rates = new ArrayList<ArrayRates>();
}
/**
* Return the number of ArrayRates objects in the collection.
*
* #return int the number of ArrayRates objects in the collection.
*
*/
public int getCount()
{
return rates.size();
}

Nothing wrong with you code since this refers to the current instance of a particular object.
Another approach could be initializing when you declare rates.
public class ArrayFun
{
// instance variables
private ArrayList<ArrayRates> rates = new ArrayList<ArrayRates>();
// constants
/**
* Tolerance variable when comparing floating point values in sort method.
*/
public static final double SORT_DELTA = .001;
/**
* Constructor for objects of class ArrayFun.
*/
public ArrayFun()
{
}
/**
* Return the number of ArrayRates objects in the collection.
*
* #return int the number of ArrayRates objects in the collection.
*
*/
public int getCount()
{
return rates.size();
}
}

There's nothing wrong with your code, in fact this is commonly used in all projects.

Related

What's the meaning of this line of code? And how can I create an object of this class?

I was trying to construct an object of the MTree class (https://github.com/Waikato/moa/blob/master/moa/src/main/java/moa/clusterers/outliers/utils/mtree/MTree.java)
The constructor of MTree looks like this:
public MTree(DistanceFunction<? super DATA> distanceFunction,
SplitFunction<DATA> splitFunction) {
this(DEFAULT_MIN_NODE_CAPACITY, distanceFunction, splitFunction);
}
The DistanceFunction here is an interface, the code of it is:
/**
* An object that can calculate the distance between two data objects.
*
* #param <DATA> The type of the data objects.
*/
public interface DistanceFunction<DATA> {
double calculate(DATA data1, DATA data2);
}
And it's implementation is:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Some pre-defined implementations of {#linkplain DistanceFunction distance
* functions}.
*/
public final class DistanceFunctions {
/**
* Don't let anyone instantiate this class.
*/
private DistanceFunctions() {}
/**
* Creates a cached version of a {#linkplain DistanceFunction distance
* function}. This method is used internally by {#link MTree} to create
* a cached distance function to pass to the {#linkplain SplitFunction split
* function}.
* #param distanceFunction The distance function to create a cached version
* of.
* #return The cached distance function.
*/
public static <Data> DistanceFunction<Data> cached(final DistanceFunction<Data> distanceFunction) {
return new DistanceFunction<Data>() {
class Pair {
Data data1;
Data data2;
public Pair(Data data1, Data data2) {
this.data1 = data1;
this.data2 = data2;
}
#Override
public int hashCode() {
return data1.hashCode() ^ data2.hashCode();
}
#Override
public boolean equals(Object arg0) {
if(arg0 instanceof Pair) {
Pair that = (Pair) arg0;
return this.data1.equals(that.data1)
&& this.data2.equals(that.data2);
} else {
return false;
}
}
}
private final Map<Pair, Double> cache = new HashMap<Pair, Double>();
#Override
public double calculate(Data data1, Data data2) {
Pair pair1 = new Pair(data1, data2);
Double distance = cache.get(pair1);
if(distance != null) {
return distance;
}
Pair pair2 = new Pair(data2, data1);
distance = cache.get(pair2);
if(distance != null) {
return distance;
}
distance = distanceFunction.calculate(data1, data2);
cache.put(pair1, distance);
cache.put(pair2, distance);
return distance;
}
};
}
/**
* An interface to represent coordinates in Euclidean spaces.
* #see <a href="http://en.wikipedia.org/wiki/Euclidean_space">"Euclidean
* Space" article at Wikipedia</a>
*/
public interface EuclideanCoordinate {
/**
* The number of dimensions.
*/
int dimensions();
/**
* A method to access the {#code index}-th component of the coordinate.
*
* #param index The index of the component. Must be less than {#link
* #dimensions()}.
*/
double get(int index);
}
/**
* Calculates the distance between two {#linkplain EuclideanCoordinate
* euclidean coordinates}.
*/
public static double euclidean(EuclideanCoordinate coord1, EuclideanCoordinate coord2) {
int size = Math.min(coord1.dimensions(), coord2.dimensions());
double distance = 0;
for(int i = 0; i < size; i++) {
double diff = coord1.get(i) - coord2.get(i);
distance += diff * diff;
}
distance = Math.sqrt(distance);
return distance;
}
/**
* A {#linkplain DistanceFunction distance function} object that calculates
* the distance between two {#linkplain EuclideanCoordinate euclidean
* coordinates}.
*/
public static final DistanceFunction<EuclideanCoordinate> EUCLIDEAN = new DistanceFunction<DistanceFunctions.EuclideanCoordinate>() {
#Override
public double calculate(EuclideanCoordinate coord1, EuclideanCoordinate coord2) {
return DistanceFunctions.euclidean(coord1, coord2);
}
};
/**
* A {#linkplain DistanceFunction distance function} object that calculates
* the distance between two coordinates represented by {#linkplain
* java.util.List lists} of {#link java.lang.Integer}s.
*/
public static final DistanceFunction<List<Integer>> EUCLIDEAN_INTEGER_LIST = new DistanceFunction<List<Integer>>() {
#Override
public double calculate(List<Integer> data1, List<Integer> data2) {
class IntegerListEuclideanCoordinate implements EuclideanCoordinate {
List<Integer> list;
public IntegerListEuclideanCoordinate(List<Integer> list) { this.list = list; }
#Override public int dimensions() { return list.size(); }
#Override public double get(int index) { return list.get(index); }
};
IntegerListEuclideanCoordinate coord1 = new IntegerListEuclideanCoordinate(data1);
IntegerListEuclideanCoordinate coord2 = new IntegerListEuclideanCoordinate(data2);
return DistanceFunctions.euclidean(coord1, coord2);
}
};
/**
* A {#linkplain DistanceFunction distance function} object that calculates
* the distance between two coordinates represented by {#linkplain
* java.util.List lists} of {#link java.lang.Double}s.
*/
public static final DistanceFunction<List<Double>> EUCLIDEAN_DOUBLE_LIST = new DistanceFunction<List<Double>>() {
#Override
public double calculate(List<Double> data1, List<Double> data2) {
class DoubleListEuclideanCoordinate implements EuclideanCoordinate {
List<Double> list;
public DoubleListEuclideanCoordinate(List<Double> list) { this.list = list; }
#Override public int dimensions() { return list.size(); }
#Override public double get(int index) { return list.get(index); }
};
DoubleListEuclideanCoordinate coord1 = new DoubleListEuclideanCoordinate(data1);
DoubleListEuclideanCoordinate coord2 = new DoubleListEuclideanCoordinate(data2);
return DistanceFunctions.euclidean(coord1, coord2);
}
};
}
And my first question is what's the meaning of return new DistanceFunction<Data>() in the method public static <Data> DistanceFunction<Data> cached(final DistanceFunction<Data> distanceFunction) [the method is in the class DistanceFunctions] I am just a beginner of Java and this one is a little bit hard for me to understand.
Also, to create an object of MTree, I should create an object of DistanceFunctions and an object of ComposedSplitFunction(Which is the implementation of SplitFunction interface) and input them as parameter for MTree constructor. But I really don't know how to do that because in DistanceFunctions class, the constructor is private. So I cannot generate a parameter for the constructor of MTree.
What should I do?
New Update: What I want to do is create a Junit Test for MTree, and I believe the first thing I need to do is create an object of MTree.
Interfaces can have multiple implementations. They just form the general contract implementations need to follow.
The cache implementation here i.e. takes a DistanceFunction as input and guarantees that distance values between A and B (or B and A) are only calculated once and thereafter served from the internal cache map. The generic type of that cache function just guarantees that you can literally pass any type to it. I.e. you could have an implementation that takes in its simplest form just two integers and calculates the difference of these like this:
DistanceFunction<Integer> func = (Integer a, Integer b) -> Math.abs(a - b);
which is a labmda expression which could be also written a bit more verbose like this
DistanceFunction<Integer> func = new DistanceFunction<Integer>() {
#Override
public double calculate(Integer data1, Integer data2) {
return Math.abs(data1 - data2);
}
};
and then use it like that to cache the return value for the provided input parameters:
DistanceFunction<Integer> cache = DistanceFunctions.cached(func);
double distance = cache.calculate(10, 5);
If you later on have a call like
distance = cache.calculate(10, 5);
again or even
distance = cache.calculate(5, 10);
The distance value in the above case is not recalculated but its value is returned from the internal cache map as the distance for these parameters was already calculated before. This is especially benefitial if you have plenty of data points but only a limited number of combination of these and calculation is rather expensive.
If you further look into the DistanceFunctions class you've provided you will see that it already provides some implementations for i.e. EUCLIDEAN, EUCLIDEAN_INTEGER_LIST and EUCLIDEAN_DOUBLE_LIST implementations which due to their static final nature can be used as constant in your code directly. Here you just need to provide matching input arguments to the calculate(...) method based on the implementation you've chosen.
In regards to Waikato's MTree` initialization, a rough template may look like this:
MTree mTree = new MTree(EUCLIDEAN_INTEGER_LIST, new SplitFunction<List<Integer>>(...) {
...
#Override
public SplitResult<List<Integer>> process(Set<List<Integer>> dataSet, DistanceFunction<? super List<Integer>> distanceFunction) {
Pair<List<Integer>> promoted = ...
Pair<Set<List<Integer>>> partitions = ...
return new SplitResult<List<Integer>>(promoted, partitions);
}
});
where the parts outlined by ... need to be defined and implemented by you. The code in that package though provides i.e. a ComposedSplitFunction implementation already that requires PartitionFunction and PromotionFunction as inputs where implementations of these are already available in the PartitionFunctions and PromotionFunctions classes that just work the same way as the DistanceFunction and DistanceFunctions discussed here.

Merge multiple RealmList´s and sort resulting List?

I just started using Realm in my current android app and so far it is great.
Unfortunately I´ve encountered a problem:
In my app the user can add different kind of entries (What did he eat this day? What drinks did he have?, etc.) into his diary.
One DiaryEntry object represents the sum off all entries for a given day (e.g. 21.05.2017, etc.).
public class DiaryEntry extends RealmObject {
// ID of the day this diary entry represents
#PrimaryKey private Integer dateId;
private RealmList<MealEntry> mealEntries;
private RealmList<DrinkEntry> drinkEntries;
private RealmList<SymptomEntry> symptomEntries;
private RealmList<MedicineEntry> medicineEntries;
public void addMealEntry(MealEntry mealEntry) {
mealEntries.add(mealEntry);
}
public RealmList<MealEntry> getMealEntries() {
return mealEntries;
}
public void addDrinkEntry(DrinkEntry drinkEntry) {
drinkEntries.add(drinkEntry);
}
public RealmList<DrinkEntry> getDrinkEntries() {
return drinkEntries;
}
public void addSymptomEntry(SymptomEntry symptomEntry) {
symptomEntries.add(symptomEntry);
}
public RealmList<SymptomEntry> getSymptomEntries() {
return symptomEntries;
}
public void addMedicineEntry(MedicineEntry medicineEntry) {
medicineEntries.add(medicineEntry);
}
public RealmList<MedicineEntry> getMedicineEntries() {
return medicineEntries;
}
}
To display this data for a particular day in the diary, all entries should be sorted by the time the user created them.
So every entry object contains a field 'time'.
private int time;
I came up with a temporary solution for my problem, but it´s far from perfect.
The follwing code is executed on the UI Thread, which obviously is bad practice.
List<RealmObject> entryList = new ArrayList<>();
OrderedRealmCollectionSnapshot<MealEntry> mealEntries = diaryEntry.getMealEntries().createSnapshot();
OrderedRealmCollectionSnapshot<DrinkEntry> drinkEntries = diaryEntry.getDrinkEntries().createSnapshot();
OrderedRealmCollectionSnapshot<MedicineEntry> medicineEntries = diaryEntry.getMedicineEntries().createSnapshot();
OrderedRealmCollectionSnapshot<SymptomEntry> symptomEntries = diaryEntry.getSymptomEntries().createSnapshot();
entryList.addAll(mealEntries);
entryList.addAll(drinkEntries);
entryList.addAll(medicineEntries);
entryList.addAll(symptomEntries);
Collections.sort(entryList, entryComparator);
The code to sort the entry list uses reflection by invoking the getter method for the time field:
public int compare(RealmObject entry1, RealmObject entry2) {
try {
Method timeGetter1 = entry1.getClass().getMethod("getTime");
Method timeGetter2 = entry2.getClass().getMethod("getTime");
int time1 = (Integer) timeGetter1.invoke(entry1);
int time2 = (Integer) timeGetter2.invoke(entry2);
return time1 - time2;
} catch (NoSuchMethodException e) {
e.printStackTrace();
Timber.d("No such method 'getTime'.");
}
// Other catch clauses
As I said earlier, all of this happens on the UI thread.
I know that I can´t pass RealmObjects, RealmLists and RealmResults across threads so I really have a hard time coming up with an async solution for that. I thought of starting a background thread and in there create copies of all the RealmList´s inside a DiaryEntry object. Then merge this unmanaged lists and sort it - all of that on the background thread.
So my question: Are there any preferred strategies for merging multiple RealmLists and sorting the merged list - all of that in an async fashion? Would my attempt I described above work?
Thanks #EpicPandaForce
I solved it exactly the way you described it and it works like a charm - now I even have the real-time functionality and no need to refresh the data manually, Nice :)
In case anybody faces the same problem I post some code pieces here that show how I solved it in code.
public class Entry extends RealmObject {
private static final int ENTRY_MEAL = 0;
private static final int ENTRY_DRINK = 1;
private static final int ENTRY_SYMPTOM = 2;
private static final int ENTRY_MEDICINE = 3;
/** The tag describes what kind of entry it represents */
private int tag;
/* Only one of these can be set, according to what this entry represents. */
#Nullable private MealEntry mealEntry;
#Nullable private DrinkEntry drinkEntry;
#Nullable private SymptomEntry symptomEntry;
#Nullable private MedicineEntry medicineEntry;
/** The time value this entry was created at */
/** Format: hours + minutes * 60 */
private int time;
public int getTime() {
return time;
}
/* Can only be accessed from within the 'data' package */
void setTime(int time) {
this.time = time;
}
/**
* Creates a new entry object in the realm database and tags it as 'MEAL'
*
* #param realm not null
* #param mealEntry the {#link MealEntry} object to map this entry to, not null
*
* #return the newly created entry
*/
static Entry createEntryAsMeal(#NonNull final Realm realm, #NonNull final MealEntry mealEntry) {
if(realm == null) {
throw new IllegalArgumentException("'realm' may not be null");
}
if(mealEntry == null) {
throw new IllegalArgumentException("'mealEntry' may not be null");
}
Entry entry = realm.createObject(Entry.class);
entry.tag = ENTRY_MEAL;
entry.mealEntry = mealEntry;
return entry;
}
/* Same methods for other tag types ... */
In MealEntry.class:
public class MealEntry extends RealmObject {
#PrimaryKey #Required private String id;
#Required private String title;
/** The entry objects this meal-entry is added to */
Entry entry;
/** This time value describes when the user consumed this meal **/
private int time;
// other fields
/**
* Creates a new MealEntry object in the realm.
* <p>
* Note: It is important to use this factory method for creating {#link MealEntry} objects in realm.
* Under the hood, a {#link Entry} object is created for every MealEntry and linked to it.
* </p>
*
* #param realm not null
*
* #return new MealEntry object which has been added to the <code>realm</code>
*/
public static MealEntry createInRealm(#NonNull Realm realm) {
if(realm == null) {
throw new IllegalArgumentException("'realm' may not be null");
}
MealEntry mealEntry = realm.createObject(MealEntry.class, UUID.randomUUID().toString());
mealEntry.entry = Entry.createEntryAsMeal(realm, mealEntry);
return mealEntry;
}
The 'time' field exists in the Entry.class and MealEntry.class so if the latter one changes the Entry must be updated accordingly:
/**
* Sets the time value for the <code>mealEntry</code> to the specified value.
* <p>
* Note: This method is necessary in order to sync the new time value with the underlying
* {#link Entry} object that is connected with the <code>mealEntry</code>.
* </p>
*
* #param mealEntry the {#link MealEntry} object to set the time for, not null
*
* #param time the new time value, must be in range of [0, 24*60] because of the format: hours*60 + minutes
*
*/
public static void setTimeForMealEntry(#NonNull MealEntry mealEntry, #IntRange(from=0, to=24*60) int time) {
if(mealEntry == null) {
throw new IllegalArgumentException("'mealEntry' may not be null");
}
mealEntry.setTime(time);
Entry entry = mealEntry.entry;
if(entry == null) {
throw new IllegalStateException("'mealEntry' contains no object of type 'Entry'! Something went wrong on creation of the 'mealEntry'");
}
/* Syncs the entries time value with the time value for this MealEntry. */
/* That´s important for sorting a list of all entries. */
entry.setTime(time);
}
Note: I could have stored only the ID of the corresponding Entry object inside the MealEntry and vice-versa for the Entry object store an ID to the corresponding MealEntry object. However I don´t know what a difference in perfomance this makes so I just went with the above approach.
One reason for the other approach though would be that I wouldn´t have to store the 'time' field twice, once in the Entry.class and once in the MealEntry.class, because in the Entry.class I could just get the time value by finding the corresponding MealEntry object by its ID and then get the time.

Can not extend directly enum [duplicate]

I want to take an existing enum and add more elements to it as follows:
enum A {a,b,c}
enum B extends A {d}
/*B is {a,b,c,d}*/
Is this possible in Java?
No, you can't do this in Java. Aside from anything else, d would then presumably be an instance of A (given the normal idea of "extends"), but users who only knew about A wouldn't know about it - which defeats the point of an enum being a well-known set of values.
If you could tell us more about how you want to use this, we could potentially suggest alternative solutions.
Enums represent a complete enumeration of possible values. So the (unhelpful) answer is no.
As an example of a real problem take weekdays, weekend days and, the union, days of week. We could define all days within days-of-week but then we would not be able to represent properties special to either weekdays and weekend-days.
What we could do, is have three enum types with a mapping between weekdays/weekend-days and days-of-week.
public enum Weekday {
MON, TUE, WED, THU, FRI;
public DayOfWeek toDayOfWeek() { ... }
}
public enum WeekendDay {
SAT, SUN;
public DayOfWeek toDayOfWeek() { ... }
}
public enum DayOfWeek {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
Alternatively, we could have an open-ended interface for day-of-week:
interface Day {
...
}
public enum Weekday implements Day {
MON, TUE, WED, THU, FRI;
}
public enum WeekendDay implements Day {
SAT, SUN;
}
Or we could combine the two approaches:
interface Day {
...
}
public enum Weekday implements Day {
MON, TUE, WED, THU, FRI;
public DayOfWeek toDayOfWeek() { ... }
}
public enum WeekendDay implements Day {
SAT, SUN;
public DayOfWeek toDayOfWeek() { ... }
}
public enum DayOfWeek {
MON, TUE, WED, THU, FRI, SAT, SUN;
public Day toDay() { ... }
}
The recommended solution to this is the extensible enum pattern.
This involves creating an interface and using that where you currently use the enum. Then make the enum implement the interface. You can add more constants by adding an additional enum/class that also extends the interface. Here is the general idea:
public interface TrafficLights {
public abstract String getColour();
}
public enum StandardTrafficLights implements TrafficLights {
RED, YELLOW, GREEN;
public String getColour() {
return name();
}
}
public enum WeirdTrafficLights implements TrafficLights {
DOUBLE_RED;
public String getColour() {
return name();
}
}
Note that if you want something like TrafficLights.valueof(String) you will have to implement it yourself.
Under the covers your ENUM is just a regular class generated by the compiler. That generated class extends java.lang.Enum. The technical reason you can't extend the generated class is that the generated class is final. The conceptual reasons for it being final are discussed in this topic. But I'll add the mechanics to the discussion.
Here is a test enum:
public enum TEST {
ONE, TWO, THREE;
}
The resulting code from javap:
public final class TEST extends java.lang.Enum<TEST> {
public static final TEST ONE;
public static final TEST TWO;
public static final TEST THREE;
static {};
public static TEST[] values();
public static TEST valueOf(java.lang.String);
}
Conceivably you could type this class on your own and drop the "final". But the compiler prevents you from extending "java.lang.Enum" directly. You could decide NOT to extend java.lang.Enum, but then your class and its derived classes would not be an instanceof java.lang.Enum ... which might not really matter to you any way!
enum A {a,b,c}
enum B extends A {d}
/*B is {a,b,c,d}*/
can be written as:
public enum All {
a (ClassGroup.A,ClassGroup.B),
b (ClassGroup.A,ClassGroup.B),
c (ClassGroup.A,ClassGroup.B),
d (ClassGroup.B)
...
ClassGroup.B.getMembers() contains {a,b,c,d}
How it can be useful: Let say we want something like:
We have events and we are using enums. Those enums can be grouped by similar processing. If we have operation with many elements, then some events starts operation, some are just step and other end the operation. To gather such operation and avoid long switch case we can group them as in example and use:
if(myEvent.is(State_StatusGroup.START)) makeNewOperationObject()..
if(myEnum.is(State_StatusGroup.STEP)) makeSomeSeriousChanges()..
if(myEnum.is(State_StatusGroup.FINISH)) closeTransactionOrSomething()..
Example:
public enum AtmOperationStatus {
STARTED_BY_SERVER (State_StatusGroup.START),
SUCCESS (State_StatusGroup.FINISH),
FAIL_TOKEN_TIMEOUT (State_StatusGroup.FAIL,
State_StatusGroup.FINISH),
FAIL_NOT_COMPLETE (State_StatusGroup.FAIL,
State_StatusGroup.STEP),
FAIL_UNKNOWN (State_StatusGroup.FAIL,
State_StatusGroup.FINISH),
(...)
private AtmOperationStatus(StatusGroupInterface ... pList){
for (StatusGroupInterface group : pList){
group.addMember(this);
}
}
public boolean is(StatusGroupInterface with){
for (AtmOperationStatus eT : with.getMembers()){
if( eT .equals(this)) return true;
}
return false;
}
// Each group must implement this interface
private interface StatusGroupInterface{
EnumSet<AtmOperationStatus> getMembers();
void addMember(AtmOperationStatus pE);
}
// DEFINING GROUPS
public enum State_StatusGroup implements StatusGroupInterface{
START, STEP, FAIL, FINISH;
private List<AtmOperationStatus> members = new LinkedList<AtmOperationStatus>();
#Override
public EnumSet<AtmOperationStatus> getMembers() {
return EnumSet.copyOf(members);
}
#Override
public void addMember(AtmOperationStatus pE) {
members.add(pE);
}
static { // forcing initiation of dependent enum
try {
Class.forName(AtmOperationStatus.class.getName());
} catch (ClassNotFoundException ex) {
throw new RuntimeException("Class AtmEventType not found", ex);
}
}
}
}
//Some use of upper code:
if (p.getStatus().is(AtmOperationStatus.State_StatusGroup.FINISH)) {
//do something
}else if (p.getStatus().is(AtmOperationStatus.State_StatusGroup.START)) {
//do something
}
Add some more advanced:
public enum AtmEventType {
USER_DEPOSIT (Status_EventsGroup.WITH_STATUS,
Authorization_EventsGroup.USER_AUTHORIZED,
ChangedMoneyAccountState_EventsGroup.CHANGED,
OperationType_EventsGroup.DEPOSIT,
ApplyTo_EventsGroup.CHANNEL),
SERVICE_DEPOSIT (Status_EventsGroup.WITH_STATUS,
Authorization_EventsGroup.TERMINAL_AUTHORIZATION,
ChangedMoneyAccountState_EventsGroup.CHANGED,
OperationType_EventsGroup.DEPOSIT,
ApplyTo_EventsGroup.CHANNEL),
DEVICE_MALFUNCTION (Status_EventsGroup.WITHOUT_STATUS,
Authorization_EventsGroup.TERMINAL_AUTHORIZATION,
ChangedMoneyAccountState_EventsGroup.DID_NOT_CHANGED,
ApplyTo_EventsGroup.DEVICE),
CONFIGURATION_4_C_CHANGED(Status_EventsGroup.WITHOUT_STATUS,
ApplyTo_EventsGroup.TERMINAL,
ChangedMoneyAccountState_EventsGroup.DID_NOT_CHANGED),
(...)
At above if we have some fail (myEvent.is(State_StatusGroup.FAIL)) then iterating by previous events we can easily check if we must revert money transfer by:
if(myEvent2.is(ChangedMoneyAccountState_EventsGroup.CHANGED)) rollBack()..
It can be useful for:
including explicite meta-data about processing logic, less to remember
implementing some of multi-inheritance
we don't want to use class structures, ex. for sending short status messages
In case you missed it, there's a chapter in the excellent Joshua Bloch's book "Effective Java, 2nd edition".
Chapter 6 - Enums and Annotations
Item 34 : Emulate extensible enums with interfaces
Just the conclusion :
A minor disadvantage of the use of interfaces to emulate extensible enums is
those implementations cannot be inherited from one enum type to another. In the
case of our Operation example, the logic to store and retrieve the symbol associated
with an operation is duplicated in BasicOperation and ExtendedOperation.
In this case, it doesn’t matter because very little code is duplicated. If there were a
a larger amount of shared functionality, you could encapsulate it in a helper class or
a static helper method to eliminate the code duplication.
In summary, while you cannot write an extensible enum type, you can
emulate it by writing an interface to go with a basic enum type that implements
the interface. This allows clients to write their own enums that implement
the interface. These enums can then be used wherever the basic enum type can be
used, assuming APIs are written in terms of the interface.
Here is a way how I found how to extend a enum into other enum, is a very straighfoward approach:
Suposse you have a enum with common constants:
public interface ICommonInterface {
String getName();
}
public enum CommonEnum implements ICommonInterface {
P_EDITABLE("editable"),
P_ACTIVE("active"),
P_ID("id");
private final String name;
EnumCriteriaComun(String name) {
name= name;
}
#Override
public String getName() {
return this.name;
}
}
then you can try to do a manual extends in this way:
public enum SubEnum implements ICommonInterface {
P_EDITABLE(CommonEnum.P_EDITABLE ),
P_ACTIVE(CommonEnum.P_ACTIVE),
P_ID(CommonEnum.P_ID),
P_NEW_CONSTANT("new_constant");
private final String name;
EnumCriteriaComun(CommonEnum commonEnum) {
name= commonEnum.name;
}
EnumCriteriaComun(String name) {
name= name;
}
#Override
public String getName() {
return this.name;
}
}
of course every time you need to extend a constant you have to modify your SubEnum files.
This is how I enhance the enum inheritance pattern with runtime check in static initializer.
The BaseKind#checkEnumExtender checks that "extending" enum declares all the values of the base enum in exactly the same way so #name() and #ordinal() remain fully compatible.
There is still copy-paste involved for declaring values but the program fails fast if somebody added or modified a value in the base class without updating extending ones.
Common behavior for different enums extending each other:
public interface Kind {
/**
* Let's say we want some additional member.
*/
String description() ;
/**
* Standard {#code Enum} method.
*/
String name() ;
/**
* Standard {#code Enum} method.
*/
int ordinal() ;
}
Base enum, with verifying method:
public enum BaseKind implements Kind {
FIRST( "First" ),
SECOND( "Second" ),
;
private final String description ;
public String description() {
return description ;
}
private BaseKind( final String description ) {
this.description = description ;
}
public static void checkEnumExtender(
final Kind[] baseValues,
final Kind[] extendingValues
) {
if( extendingValues.length < baseValues.length ) {
throw new IncorrectExtensionError( "Only " + extendingValues.length + " values against "
+ baseValues.length + " base values" ) ;
}
for( int i = 0 ; i < baseValues.length ; i ++ ) {
final Kind baseValue = baseValues[ i ] ;
final Kind extendingValue = extendingValues[ i ] ;
if( baseValue.ordinal() != extendingValue.ordinal() ) {
throw new IncorrectExtensionError( "Base ordinal " + baseValue.ordinal()
+ " doesn't match with " + extendingValue.ordinal() ) ;
}
if( ! baseValue.name().equals( extendingValue.name() ) ) {
throw new IncorrectExtensionError( "Base name[ " + i + "] " + baseValue.name()
+ " doesn't match with " + extendingValue.name() ) ;
}
if( ! baseValue.description().equals( extendingValue.description() ) ) {
throw new IncorrectExtensionError( "Description[ " + i + "] " + baseValue.description()
+ " doesn't match with " + extendingValue.description() ) ;
}
}
}
public static class IncorrectExtensionError extends Error {
public IncorrectExtensionError( final String s ) {
super( s ) ;
}
}
}
Extension sample:
public enum ExtendingKind implements Kind {
FIRST( BaseKind.FIRST ),
SECOND( BaseKind.SECOND ),
THIRD( "Third" ),
;
private final String description ;
public String description() {
return description ;
}
ExtendingKind( final BaseKind baseKind ) {
this.description = baseKind.description() ;
}
ExtendingKind( final String description ) {
this.description = description ;
}
}
Based on #Tom Hawtin - tackline answer we add switch support,
interface Day<T> {
...
T valueOf();
}
public enum Weekday implements Day<Weekday> {
MON, TUE, WED, THU, FRI;
Weekday valueOf(){
return valueOf(name());
}
}
public enum WeekendDay implements Day<WeekendDay> {
SAT, SUN;
WeekendDay valueOf(){
return valueOf(name());
}
}
Day<Weekday> wds = Weekday.MON;
Day<WeekendDay> wends = WeekendDay.SUN;
switch(wds.valueOf()){
case MON:
case TUE:
case WED:
case THU:
case FRI:
}
switch(wends.valueOf()){
case SAT:
case SUN:
}
I tend to avoid enums, because they are not extensible. To stay with the example of the OP, if A is in a library and B in your own code, you can't extend A if it is an enum. This is how I sometimes replace enums:
// access like enum: A.a
public class A {
public static final A a = new A();
public static final A b = new A();
public static final A c = new A();
/*
* In case you need to identify your constant
* in different JVMs, you need an id. This is the case if
* your object is transfered between
* different JVM instances (eg. save/load, or network).
* Also, switch statements don't work with
* Objects, but work with int.
*/
public static int maxId=0;
public int id = maxId++;
public int getId() { return id; }
}
public class B extends A {
/*
* good: you can do like
* A x = getYourEnumFromSomeWhere();
* if(x instanceof B) ...;
* to identify which enum x
* is of.
*/
public static final A d = new A();
}
public class C extends A {
/* Good: e.getId() != d.getId()
* Bad: in different JVMs, C and B
* might be initialized in different order,
* resulting in different IDs.
* Workaround: use a fixed int, or hash code.
*/
public static final A e = new A();
public int getId() { return -32489132; };
}
There are some pits to avoid, see the comments in the code. Depending on your needs, this is a solid, extensible alternative to enums.
I suggest you take the other way around approach.
Instead of extending the existing enumeration, create a larger one and create a subset of it.
For exemple if you had an enumeration called PET and you wanted to extend it to ANIMAL you should do this instead:
public enum ANIMAL {
WOLF,CAT, DOG
}
EnumSet<ANIMAL> pets = EnumSet.of(ANIMAL.CAT, ANIMAL.DOG);
Be careful, pets is not an immutable collections, you might want to use Guava or Java9 for more safety.
As an aid to understanding why extending an Enum is not reasonable at the language implementation level to consider what would happen if you passed an instance of the extended Enum to a routine that only understands the base Enum. A switch that the compiler promised had all cases covered would in fact not cover those extended Enum values.
This further emphasizes that Java Enum values are not integers such as C's are, for instances: to use a Java Enum as an array index you must explicitly ask for its ordinal() member, to give a java Enum an arbitrary integer value you must add an explicit field for that and reference that named member.
This is not a comment on the OP's desire, just on why Java ain't never going to do it.
Having had this same problem myself I'd like to post my perspective. I think that there are a couple motivating factors for doing something like this:
You want to have some related enum codes, but in different classes. In my case I had a base class with several codes defined in an associated enum. At some later date (today!) I wanted to provide some new functionality to the base class, which also meant new codes for the enum.
The derived class would support both the base classes' enum as well as its own. No duplicate enum values! So: how to have an enum for the subclass that includes the enum's of its parent along with its new values.
Using an interface doesn't really cut it: you can accidentally get duplicate enum values. Not desirable.
I ended up just combining the enums: this ensures that there cannot be any duplicate values, at the expense of being less tightly tied to its associated class. But, I figured the duplicate issue was my main concern...
In the hopes this elegant solution of a colleague of mine is even seen in this long post I'd like to share this approach for subclassing which follows the interface approach and beyond.
Please be aware that we use custom exceptions here and this code won't compile unless you replace it with your exceptions.
The documentation is extensive and I hope it's understandable for most of you.
The interface that every subclassed enum needs to implement.
public interface Parameter {
/**
* Retrieve the parameters name.
*
* #return the name of the parameter
*/
String getName();
/**
* Retrieve the parameters type.
*
* #return the {#link Class} according to the type of the parameter
*/
Class<?> getType();
/**
* Matches the given string with this parameters value pattern (if applicable). This helps to find
* out if the given string is a syntactically valid candidate for this parameters value.
*
* #param valueStr <i>optional</i> - the string to check for
* #return <code>true</code> in case this parameter has no pattern defined or the given string
* matches the defined one, <code>false</code> in case <code>valueStr</code> is
* <code>null</code> or an existing pattern is not matched
*/
boolean match(final String valueStr);
/**
* This method works as {#link #match(String)} but throws an exception if not matched.
*
* #param valueStr <i>optional</i> - the string to check for
* #throws ArgumentException with code
* <dl>
* <dt>PARAM_MISSED</dt>
* <dd>if <code>valueStr</code> is <code>null</code></dd>
* <dt>PARAM_BAD</dt>
* <dd>if pattern is not matched</dd>
* </dl>
*/
void matchEx(final String valueStr) throws ArgumentException;
/**
* Parses a value for this parameter from the given string. This method honors the parameters data
* type and potentially other criteria defining a valid value (e.g. a pattern).
*
* #param valueStr <i>optional</i> - the string to parse the parameter value from
* #return the parameter value according to the parameters type (see {#link #getType()}) or
* <code>null</code> in case <code>valueStr</code> was <code>null</code>.
* #throws ArgumentException in case <code>valueStr</code> is not parsable as a value for this
* parameter.
*/
Object parse(final String valueStr) throws ArgumentException;
/**
* Converts the given value to its external form as it is accepted by {#link #parse(String)}. For
* most (ordinary) parameters this is simply a call to {#link String#valueOf(Object)}. In case the
* parameter types {#link Object#toString()} method does not return the external form (e.g. for
* enumerations), this method has to be implemented accordingly.
*
* #param value <i>mandatory</i> - the parameters value
* #return the external form of the parameters value, never <code>null</code>
* #throws InternalServiceException in case the given <code>value</code> does not match
* {#link #getType()}
*/
String toString(final Object value) throws InternalServiceException;
}
The implementing ENUM base class.
public enum Parameters implements Parameter {
/**
* ANY ENUM VALUE
*/
VALUE(new ParameterImpl<String>("VALUE", String.class, "[A-Za-z]{3,10}"));
/**
* The parameter wrapped by this enum constant.
*/
private Parameter param;
/**
* Constructor.
*
* #param param <i>mandatory</i> - the value for {#link #param}
*/
private Parameters(final Parameter param) {
this.param = param;
}
/**
* {#inheritDoc}
*/
#Override
public String getName() {
return this.param.getName();
}
/**
* {#inheritDoc}
*/
#Override
public Class<?> getType() {
return this.param.getType();
}
/**
* {#inheritDoc}
*/
#Override
public boolean match(final String valueStr) {
return this.param.match(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public void matchEx(final String valueStr) {
this.param.matchEx(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public Object parse(final String valueStr) throws ArgumentException {
return this.param.parse(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public String toString(final Object value) throws InternalServiceException {
return this.param.toString(value);
}
}
The subclassed ENUM which "inherits" from base class.
public enum ExtendedParameters implements Parameter {
/**
* ANY ENUM VALUE
*/
VALUE(my.package.name.VALUE);
/**
* EXTENDED ENUM VALUE
*/
EXTENDED_VALUE(new ParameterImpl<String>("EXTENDED_VALUE", String.class, "[0-9A-Za-z_.-]{1,20}"));
/**
* The parameter wrapped by this enum constant.
*/
private Parameter param;
/**
* Constructor.
*
* #param param <i>mandatory</i> - the value for {#link #param}
*/
private Parameters(final Parameter param) {
this.param = param;
}
/**
* {#inheritDoc}
*/
#Override
public String getName() {
return this.param.getName();
}
/**
* {#inheritDoc}
*/
#Override
public Class<?> getType() {
return this.param.getType();
}
/**
* {#inheritDoc}
*/
#Override
public boolean match(final String valueStr) {
return this.param.match(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public void matchEx(final String valueStr) {
this.param.matchEx(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public Object parse(final String valueStr) throws ArgumentException {
return this.param.parse(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public String toString(final Object value) throws InternalServiceException {
return this.param.toString(value);
}
}
Finally the generic ParameterImpl to add some utilities.
public class ParameterImpl<T> implements Parameter {
/**
* The default pattern for numeric (integer, long) parameters.
*/
private static final Pattern NUMBER_PATTERN = Pattern.compile("[0-9]+");
/**
* The default pattern for parameters of type boolean.
*/
private static final Pattern BOOLEAN_PATTERN = Pattern.compile("0|1|true|false");
/**
* The name of the parameter, never <code>null</code>.
*/
private final String name;
/**
* The data type of the parameter.
*/
private final Class<T> type;
/**
* The validation pattern for the parameters values. This may be <code>null</code>.
*/
private final Pattern validator;
/**
* Shortcut constructor without <code>validatorPattern</code>.
*
* #param name <i>mandatory</i> - the value for {#link #name}
* #param type <i>mandatory</i> - the value for {#link #type}
*/
public ParameterImpl(final String name, final Class<T> type) {
this(name, type, null);
}
/**
* Constructor.
*
* #param name <i>mandatory</i> - the value for {#link #name}
* #param type <i>mandatory</i> - the value for {#link #type}
* #param validatorPattern - <i>optional</i> - the pattern for {#link #validator}
* <dl>
* <dt style="margin-top:0.25cm;"><i>Note:</i>
* <dd>The default validation patterns {#link #NUMBER_PATTERN} or
* {#link #BOOLEAN_PATTERN} are applied accordingly.
* </dl>
*/
public ParameterImpl(final String name, final Class<T> type, final String validatorPattern) {
this.name = name;
this.type = type;
if (null != validatorPattern) {
this.validator = Pattern.compile(validatorPattern);
} else if (Integer.class == this.type || Long.class == this.type) {
this.validator = NUMBER_PATTERN;
} else if (Boolean.class == this.type) {
this.validator = BOOLEAN_PATTERN;
} else {
this.validator = null;
}
}
/**
* {#inheritDoc}
*/
#Override
public boolean match(final String valueStr) {
if (null == valueStr) {
return false;
}
if (null != this.validator) {
final Matcher matcher = this.validator.matcher(valueStr);
return matcher.matches();
}
return true;
}
/**
* {#inheritDoc}
*/
#Override
public void matchEx(final String valueStr) throws ArgumentException {
if (false == this.match(valueStr)) {
if (null == valueStr) {
throw ArgumentException.createEx(ErrorCode.PARAM_MISSED, "The value must not be null",
this.name);
}
throw ArgumentException.createEx(ErrorCode.PARAM_BAD, "The value must match the pattern: "
+ this.validator.pattern(), this.name);
}
}
/**
* Parse the parameters value from the given string value according to {#link #type}. Additional
* the value is checked by {#link #matchEx(String)}.
*
* #param valueStr <i>optional</i> - the string value to parse the value from
* #return the parsed value, may be <code>null</code>
* #throws ArgumentException in case the parameter:
* <ul>
* <li>does not {#link #matchEx(String)} the {#link #validator}</li>
* <li>cannot be parsed according to {#link #type}</li>
* </ul>
* #throws InternalServiceException in case the type {#link #type} cannot be handled. This is a
* programming error.
*/
#Override
public T parse(final String valueStr) throws ArgumentException, InternalServiceException {
if (null == valueStr) {
return null;
}
this.matchEx(valueStr);
if (String.class == this.type) {
return this.type.cast(valueStr);
}
if (Boolean.class == this.type) {
return this.type.cast(Boolean.valueOf(("1".equals(valueStr)) || Boolean.valueOf(valueStr)));
}
try {
if (Integer.class == this.type) {
return this.type.cast(Integer.valueOf(valueStr));
}
if (Long.class == this.type) {
return this.type.cast(Long.valueOf(valueStr));
}
} catch (final NumberFormatException e) {
throw ArgumentException.createEx(ErrorCode.PARAM_BAD, "The value cannot be parsed as "
+ this.type.getSimpleName().toLowerCase() + ".", this.name);
}
return this.parseOther(valueStr);
}
/**
* Field access for {#link #name}.
*
* #return the value of {#link #name}.
*/
#Override
public String getName() {
return this.name;
}
/**
* Field access for {#link #type}.
*
* #return the value of {#link #type}.
*/
#Override
public Class<T> getType() {
return this.type;
}
/**
* {#inheritDoc}
*/
#Override
public final String toString(final Object value) throws InternalServiceException {
if (false == this.type.isAssignableFrom(value.getClass())) {
throw new InternalServiceException(ErrorCode.PANIC,
"Parameter.toString(): Bad type of value. Expected {0} but is {1}.", this.type.getName(),
value.getClass().getName());
}
if (String.class == this.type || Integer.class == this.type || Long.class == this.type) {
return String.valueOf(value);
}
if (Boolean.class == this.type) {
return Boolean.TRUE.equals(value) ? "1" : "0";
}
return this.toStringOther(value);
}
/**
* Parse parameter values of other (non standard types). This method is called by
* {#link #parse(String)} in case {#link #type} is none of the supported standard types (currently
* String, Boolean, Integer and Long). It is intended for extensions.
* <dl>
* <dt style="margin-top:0.25cm;"><i>Note:</i>
* <dd>This default implementation always throws an InternalServiceException.
* </dl>
*
* #param valueStr <i>mandatory</i> - the string value to parse the value from
* #return the parsed value, may be <code>null</code>
* #throws ArgumentException in case the parameter cannot be parsed according to {#link #type}
* #throws InternalServiceException in case the type {#link #type} cannot be handled. This is a
* programming error.
*/
protected T parseOther(final String valueStr) throws ArgumentException, InternalServiceException {
throw new InternalServiceException(ErrorCode.PANIC,
"ParameterImpl.parseOther(): Unsupported parameter type: " + this.type.getName());
}
/**
* Convert the values of other (non standard types) to their external form. This method is called
* by {#link #toString(Object)} in case {#link #type} is none of the supported standard types
* (currently String, Boolean, Integer and Long). It is intended for extensions.
* <dl>
* <dt style="margin-top:0.25cm;"><i>Note:</i>
* <dd>This default implementation always throws an InternalServiceException.
* </dl>
*
* #param value <i>mandatory</i> - the parameters value
* #return the external form of the parameters value, never <code>null</code>
* #throws InternalServiceException in case the given <code>value</code> does not match
* {#link #getClass()}
*/
protected String toStringOther(final Object value) throws InternalServiceException {
throw new InternalServiceException(ErrorCode.PANIC,
"ParameterImpl.toStringOther(): Unsupported parameter type: " + this.type.getName());
}
}
My way to code that would be as follows:
// enum A { a, b, c }
static final Set<Short> enumA = new LinkedHashSet<>(Arrays.asList(new Short[]{'a','b','c'}));
// enum B extends A { d }
static final Set<Short> enumB = new LinkedHashSet<>(enumA);
static {
enumB.add((short) 'd');
// If you have to add more elements:
// enumB.addAll(Arrays.asList(new Short[]{ 'e', 'f', 'g', '♯', '♭' }));
}
LinkedHashSet provides both that each entry only exists once, and that their order is preserved. If order doesn’t matter, you can use HashSet instead. The following code is not possible in Java:
for (A a : B.values()) { // enum B extends A { d }
switch (a) {
case a:
case b:
case c:
System.out.println("Value is: " + a.toString());
break;
default:
throw new IllegalStateException("This should never happen.");
}
}
The code can be written as follows:
for (Short a : enumB) {
switch (a) {
case 'a':
case 'b':
case 'c':
System.out.println("Value is: " + new String(Character.toChars(a)));
break;
default:
throw new IllegalStateException("This should never happen.");
}
}
From Java 7 onwards you can even do the same with String:
// enum A { BACKWARDS, FOREWARDS, STANDING }
static final Set<String> enumA = new LinkedHashSet<>(Arrays.asList(new String[] {
"BACKWARDS", "FOREWARDS", "STANDING" }));
// enum B extends A { JUMP }
static final Set<String> enumB = new LinkedHashSet<>(enumA);
static {
enumB.add("JUMP");
}
Using the enum replacement:
for (String a : enumB) {
switch (a) {
case "BACKWARDS":
case "FOREWARDS":
case "STANDING":
System.out.println("Value is: " + a);
break;
default:
throw new IllegalStateException("This should never happen.");
}
}

How to change values in the SET Method

I am starting to develop my skills in JAVA, however I have a doubt.
I'm creating an object in JAVA, created the constructor and so on, then, it asks "Change the AGE_RECENT value from 1 to 3", I initially declared this as final because I never thought it would change, so no SET or GET were created. I am wondering how can I change the value from 1 to 3 in the SET Method.
I have this variable
private static int AGE_RECENT=1;
I did this.
public void setAgeRecent() {
Vehicle.AGE_RECENT = 3;
}
It works if you run the program, it changes the variable's value, however nothing was declared in that method as every SET method.
Just wondering how can I do this. If this is correct, good, if not, thanks for helping!
As someone asked, the code.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tp1;
/**
*
* #author Nelson
*/
public class Vehicle {
/** Variáveis da classe, têm como função **/
private String registration;
private int registrationYear;
private double consumption;
private double autonomy;
private int cilinderCapacity;
/**
* Final variables. They are final because they do not suffer any kind of modification during the project.
* YEAR_OMISSION is 2016 because the currect year is 2016.
* ENVIRONMENTAL_CHARGE_OMISSION is 0.10(10 cents), gave this value because there is nothing to mention the
especific value, hence why I gave 0.10.
* RATING_RECENT = Is a string, just has the text "RECENT" inside.
* RATING_COMTEMPORY - Another string, just with the "Comtempory" text inside.
* RATING_CLASSIC - Yet again another string, with the "Classic" text.
* AGE_RECENT - It is to help to compare if a vehicle is recent or not, it has the value 3.
* AGE_CLASSIC - It is to again help to compare, value is 20.
*/
private static final int YEAR_OMISSION = 2016;
private static final double ENVIRONMENTAL_CHARGE_OMISSION=0.10;
private static final String RATING_RECENT="Recent";
private static final String RATING_CONTEMPORY="Contempory";
private static final String RATING_CLASSIC="Classic";
private static int AGE_RECENT=1;
private static final int AGE_CLASSIC=20;
/**
* Constructor of the object, it has the Registration
* #param registration
* #param registrationYear - The year the vehicle was first registered.
* #param consumption - How many liters the vehicle consumes.
* #param autonomy - How many KMs a vehicle can go without refuelling.
* #param cilinderCapacity - How many Cubic Inches the engine has.
*/
public Vehicle(String registration,int registrationYear, double consumption, double autonomy, int cilinderCapacity) {
this.registration = registration;
this.registrationYear = registrationYear;
this.consumption = consumption;
this.autonomy = autonomy;
this.cilinderCapacity = cilinderCapacity;
}
/**
* Null Constructor, it has no values, they will be attributed in the MAIN Class.
*/
public Vehicle() {
this.registration = "";
this.registrationYear = 0;
this.consumption = 0;
this.autonomy = 0;
this.cilinderCapacity =0;
this.registrationYear = YEAR_OMISSION;
}
/**
* Copy Constructor.
*/
public Vehicle(Vehicle vehicle) {
this.registration = vehicle.getRegistration();
this.registrationYear = vehicle.getRegistrationYear();
this.consumption = vehicle.getConsumption();
this.autonomy = vehicle.getAutonomy();
this.cilinderCapacity = vehicle.getCilinderCapacity();
}
public String getRegistration() {
return registration;
}
public int getRegistrationYear() {
return registrationYear;
}
public double getConsumption() {
return consumption;
}
public double getAutonomy() {
return autonomy;
}
public int getCilinderCapacity() {
return cilinderCapacity;
}
public double getYearRecent() {
return AGE_RECENT;
}
public double getAgeRecent(){
return AGE_RECENT;
}
public void setRegistration(String registration) {
this.registration = registration;
}
public void setRegistrationYear(int registrationYear) {
this.registrationYear = registrationYear;
}
public void setConsumption(double consumption) {
this.consumption = consumption;
}
public void setAutonomy(double autonomy) {
this.autonomy = autonomy;
}
public void setCilinderCapacity(int cilinderCapacity) {
this.cilinderCapacity = cilinderCapacity;
}
public void setAgeRecent() {
Vehicle.AGE_RECENT = 3;
}
/**
* Calculate the age of the vehicle to compare in the vehicleRating method
* #return The year, which is 2016 minus the year the vehicle was first registered.
*/
private int calculateAge(){
return YEAR_OMISSION-this.registrationYear;
}
/**
* Calculate the Circulation Tax.
* #return Returns the value of the Environmental Charge multiplied by the Cilinder Capacity of the vehicle.
*/
public double calculateCirculationTax(){
return ENVIRONMENTAL_CHARGE_OMISSION*cilinderCapacity;
}
/**
* Classify the vehicle based on the age.
* If the result given by the calculateAge method is minor than the AGE_RECENT variable(3), then it will
return "Recent"
* If the result is between Age_RECENT and AGE_CLASSIC(20), then it will say "Contemporary"
* If none of the IFs apply, it will return "Classic".
**/
public static String vehicleRating(Vehicle vehicle) {
if(vehicle.calculateAge() < Vehicle.AGE_RECENT) {
return Vehicle.RATING_RECENT; }
else if ((vehicle.calculateAge()>=Vehicle.AGE_RECENT)&&(vehicle.calculateAge()<=Vehicle.AGE_CLASSIC)){
return Vehicle.RATING_CONTEMPORY;}
else
return Vehicle.RATING_CLASSIC;
}
#Override
public String toString() {
return "Vehicle{" + "registration=" + registration + ", registrationYear=" + registrationYear + ", consumption=" + consumption + ", autonomy=" + autonomy + ", cilinderCapacity=" + cilinderCapacity + '}';
}
}
A setter that takes no arguments is simply a method, not a setter. In order to work as a setter a method must take a parameter that matches the type of the value being set - in your case, that would be int:
public static void setAgeRecent(int age) {
AGE_RECENT = age;
}
Note a few things here:
Since AGE_RECENT is static, setAgeRecent should be static
Since AGE_RECENT and setAgeRecent are static members of the same class Vehicle, you do not need to qualify AGE_RECENT with Vehicle
Now users of your class would be able to call your static setter as follows:
Vehicle.setAgeRecent(3);
A static varible, or class variable, may be used without the need to create an instance of that class. But its value may be changed freely at runtime.
A final variable is not a variable in a true sense, because it's value can't be changed at runtime.
Thus, you may have a set method for a static variable, but never to a final variable.

League Table order points

I need to have the teams sortable by order of points, from most to least, i have that i have to write a new method and can make changes to the class header.
I was thinking of using this as my method, but it would put the teams in order of least to most :S so i dont know what way to fix it, also i dont know what changes i would need to make to the class header if any!
public void orderPoints()
{
List<String> points = new ArrayList<String>();
Collections.sort(points);
}
I know i can use Collections.max and min but unsure how i would filter the rest of the points in
Code for rest of the class
public class League
{ /* instance
variables */
private Team name;
private int points;
/**
* Constructor for objects of class League.
*/ public League(Team aname)
{
super();
name = aName;
points = 0; }
/**
* Returns the receiver's name Team
*/ public Team getName() {
return this.name; }
/**
* Returns the receiver's points
*/ public int getPoints() {
return points; }
/**
* Sets the receiver's points
*/ public void setPoints(int aPoints) {
this.points = aPoints; }
I'm not sure I understand what you're asking, but if you want to reverse the sorting of your List you can use Collections.sort(points, Collections.reverseOrder());

Categories