How to change values in the SET Method - java

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.

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.

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.");
}
}

Incompatible Object Types - Java

I'm trying to implement a small Java program which shows how process scheduling works. My current code is below. The issue I'm having is with the static method CPU.executeInstructions(Process process) and firstComeFirstServed() from the ProcessScheduler class. My program currently won't compile as it gives
incompatible type error: Object can not be converted to Process
from within firstComeFirstServed().
I've managed to make it compile by changing executeInstructions() argument from Process process to Object process, but as far as I can see there is nothing wrong with the previous method signature. I've thrown a couple of System.out.println() calls in around the program to print the class to the screen, which confirms that the object being operated on is a Process object. Can somebody explain what is going on here? What am I missing/not understanding?
package processes;
import java.util.logging.Level;
import java.util.logging.Logger;
import processes.ProcessScheduler.Algorithm;
public class ProcessManager {
private static Thread psThread;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// Create process table
ProcessTable pt;
//System.out.println("1 " + pt.getClass());
// Creat Process Scheduling Thread.
psThread = new Thread(new ProcessScheduler(Algorithm.FIRST_COME_FIRST_SERVE, pt = new ProcessTable()));
System.out.println("2 " + pt.getClass());
// Start Thread
psThread.start();
System.out.println("3 " + pt.getClass());
try {
// Add Process' to table
String[] instrucSet = {"sout","name"};
for(int i = 0; i < 5; i++){
pt.add(new Process(ProcessTable.processCounter, i + 1, 10 - i, instrucSet));
}
Thread.sleep(4000);
for(int i = 0; i < 5; i++){
pt.add(new Process(ProcessTable.processCounter, i + 1, 10 - i, instrucSet));
}
Thread.sleep(2000);
ProcessScheduler.run = false;
} catch (InterruptedException ex) {
Logger.getLogger(ProcessManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
package processes;
public class Process {
private int quanta, priority, pID;
private String [] instructions;
/**
* Constructor for Process class.
* #param p_id process id
* #param instruction_set Instructions to be processed by the CPU.
* #param quanta Represents length of time (known or estimated) taken to execute process
*/
public Process(int p_id, int quanta, String instruction_set[]){
// Initialise instance variables
this.pID = p_id;
this.quanta = quanta;
this.instructions = instruction_set;
}
/**
* Constructor for Process class.
* #param quanta Represents length of time (known or estimated) taken to execute process
* #param priority Represents the priority of the process, from 1 to infinity with 1 having highest priority.
* #param instruction_set Instructions to be processed by the CPU.
*/
public Process(int p_id,int quanta, int priority, String instruction_set[]){
// Initialise instance variables
this.pID = p_id;
this.quanta = quanta;
this.priority = priority;
this.instructions = instruction_set;
}
/**
* #return Returns length of process, which may either be a known or estimated quantity.
*/
public int getQuanta() {
return quanta;
}
/**
* #return Returns process priority level.
*/
public int getPriority() {
return priority;
}
/**
* #return Returns process id, a unique value generated when the process is accepted onto the process table.
*/
public int getpID() {
return pID;
}
/**
* #return Returns an array holding the instructions to be processed for this process.
*/
public String[] getInstructions() {
return instructions;
}
#Override
public String toString(){
return "Process ID: " + this.getpID() + ". Quanta: " + this.getQuanta() + ". Priority: " + this.getPriority();
}
}
package processes;
import java.util.ArrayList;
/**
*
* #author dave
*/
public class ProcessTable extends ArrayList {
// P_id counter;
public static int processCounter = 0;
public ProcessTable(){
super();
}
/**
* Adds the specified process to the collection and increments the processCounter
* #param aProcess The process to be added to the Process Table.
* #return Returns true if successfully added.
*/
public boolean add(Process aProcess){
boolean sucessful = super.add(aProcess);
if(sucessful)
processCounter++;
return sucessful;
}
/**
* Prints the process table to console.
*/
public void displayProcessTable(){
for(int i = 0; i < this.size(); i++){
System.out.println(this.get(i).toString());
}
}
}
package processes;
/**
*
* #author dave
*/
public final class CPU {
private CPU(){
}
public static void executeInstructions(Process process){
System.out.println(process.toString());
}
}
package processes;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* #author dave
*/
public class ProcessScheduler implements Runnable {
public static boolean run;
// The algorithm to be used.
private String alg;
// To hold reference to a Proces Table.
public static ProcessTable pt;
// Class constants for scheduling algorithm type. Used in class constructor.
// Enum for
public enum Algorithm {FIRST_COME_FIRST_SERVE, SHORTEST_JOB_FIRST, ROUND_ROBIN, PRIORITY_QUEUE};
/**
* #param scheduling_algorithm Sets the scheduling algorithm to be used when
* #param process_table A Process Table instant that Process will be added to.
* passing jobs to the CPU for execution.
*/
public ProcessScheduler(Algorithm scheduling_algorithm, ProcessTable process_table){
//System.out.println("4 " + pt.getClass());
// Create reference Process Table
//pt = new ProcessTable();
pt = process_table;
System.out.println("5 " + pt.getClass());
// Start scheduling based on algorithm represented by enum in constructor arg.
switch(scheduling_algorithm){
case FIRST_COME_FIRST_SERVE:
alg = "fcfs";
break;
case SHORTEST_JOB_FIRST:
alg = "sjf";
break;
case ROUND_ROBIN:
alg = "rr";
case PRIORITY_QUEUE:
alg = "pq";
default:
alg = "pq";
break;
}
}
/**
* Start Scheduling processes to the CPU
*/
public void run() {
//boolean run = true;
int sleepTime = 1000;
//Display algorithm to screen
try {
run = true;
while(run){
if(!pt.isEmpty()){
switch (alg) {
case "fcfs":
System.out.println("6 " + pt.getClass());
firstComeFirstServed();
break;
case "sjf":
shortestJobFirst();
break;
case "rr":
roundRobin();
break;
case "pq":
priorityQueue();
break;
}
} else {
Thread.sleep(sleepTime);
}
}
} catch (InterruptedException ex) {
Logger.getLogger(ProcessScheduler.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Executes all processes in Process Table on a First Come First Served
* basis (the order in which they were added to the collection).
*/
private void firstComeFirstServed(){
System.out.println("7 " + pt.getClass());
for(int i = 0; i < pt.size(); i++){
CPU.executeInstructions(pt.get(i));
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(ProcessScheduler.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void shortestJobFirst(){
System.out.println("in SJF");
}
private void roundRobin(){
System.out.println("in RR");
}
private void priorityQueue(){
System.out.println("in PQ");
}
}
As others have noted, ProcessTable should extend ArrayList<Process>. However there isn't much reason for the ProcessTable class to exist at all. All is does is provide an incorrectly implemented counter (should not be static) and a display method. I would remove it and just use ArrayList<Process>.
Your ProcessTable definition should be like this:
public static class ProcessTable extends ArrayList<Process>
The problem is your ProcessTable class that extends ArrayList is not generic.
You can start by modifying it with
public class ProcessTable<E> extends ArrayList<E> {
Then when you instantiate it, you can specify the class type ProcessTable will hold inside
ProcessTable<Process> pt;
That way the compiler will know which class will return the pt.get(i) call.
if not, it will treat it as Object.
EDIT:
As #EJP noted, being more specific to your problem you probably want to extend ArrayList with the specific class type it will work with
public class ProcessTable extends ArrayList<Process>

Creating an array object from a constructor in 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.

Cannot make static reference to non-static object

This is my first Java project.
So I'm working on my own simulation project, and some of my core stuff has gone awry. I have two classes I'm focusing on right now - settlement and townRey, which extends settlement.
The error is thrown when I try
System.out.println(townRey.returnStrength());
Here are my two relevant classes:
settlement:
public class settlement
{
//
//
// VARIABLES
//
//
/**
* The town's unique name.
*/
public String name;
/**
* The settlement's location in latitude (N-S)
*/
public int latitude;
/**
* The settlement's location in longitude (E-W)
*/
public int longitude;
/**
* What faction a town or village is aligned to. This determines production and consumption, mostly.
*/
public String faction;
/**
* What a specific village or town produces.
*/
public String[] production;
/**
* What a specific town consumes (villages don't consume)
*/
public String[] consumption;
/**
* How dangerous a specific town is with bandits
* A 1-10 scale, with 10 being the most dangerous.
* Any town with a danger over 8 can be raided and destroyed temporarily by bandits.
* Being raided successfully depends on the Strength of a town.
*/
public int danger;
/**
* How much a town takes in taxes.
*/
public float tax;
/**
* How easily a town is raided by bandits.
* If a bandit raid has a lower strength than the town, then the town wins.
*/
public int strength;
//
//
// METHODS
//
//
public int returnLatitude()
{
return latitude;
}
public int returnLongitude()
{
return longitude;
}
public String returnFaction()
{
return faction;
}
public String[] returnProduction()
{
return production;
}
public String[] returnConsumption()
{
return consumption;
}
public int returnDanger()
{
return danger;
}
public float returnTax()
{
return tax;
}
public int returnStrength()
{
return strength;
}
}
and townRey:
public class townRey extends settlement
{{
name = "Rey";
latitude = 5;
longitude = 5;
String faction = "Nord";
String[] production;
String[] consumption;
danger = 1;
tax = 0.05F;
strength = 6;
}}
EDIT:: Thanks for all the help! I fixed all issues now. Below is 'Settlement' and 'Start'.
public class Settlement
{
//
//
// VARIABLES
//
//
/**
* The town's unique name.
*/
public String name;
/**
* The settlement's location in latitude (N-S)
*/
public int latitude;
/**
* The settlement's location in longitude (E-W)
*/
public int longitude;
/**
* What faction a town or village is aligned to. This determines production and consumption, mostly.
*/
public String faction;
/**
* What a specific village or town produces.
*/
public String[] production;
/**
* What a specific town consumes (villages don't consume)
*/
public String[] consumption;
/**
* How dangerous a specific town is with bandits
* A 1-10 scale, with 10 being the most dangerous.
* Any town with a danger over 8 can be raided and destroyed temporarily by bandits.
* Being raided successfully depends on the Strength of a town.
*/
public int danger;
/**
* How much a town takes in taxes.
*/
public float tax;
/**
* How easily a town is raided by bandits.
* If a bandit raid has a lower strength than the town, then the town wins.
*/
public int strength;
//
//
// METHODS
//
//
public int returnLatitude()
{
return latitude;
}
public int returnLongitude()
{
return longitude;
}
public String returnFaction()
{
return faction;
}
public String[] returnProduction()
{
return production;
}
public String[] returnConsumption()
{
return consumption;
}
public int returnDanger()
{
return danger;
}
public float returnTax()
{
return tax;
}
public int returnStrength()
{
return strength;
}
}
and Start, where I create 'townRey' then access a bit of data in two different ways.
public class Start
{
public static void main(String[] args)
{
//Creates 'Rey'
Settlement townRey = new Settlement();
townRey.name = "Rey";
townRey.latitude = 5;
townRey.longitude = 5;
townRey.faction = "Nord";
townRey.danger = 1;
townRey.tax = 0.05F;
townRey.strength = 6;
//This calls the returnLongitude method from Settlement, and is the 'proper' way to do it.
System.out.println(townRey.returnLongitude());
//This also works.
System.out.println(townRey.longitude);
//Thanks for the help!
}
}
townRey shouldn't be extending settlement. You should be declaring it as an instance of settlement in some method, as follows:
townRey = new settlement();
townRey.name = "Rey";
...
townRey.strength = 6;
Or, better still, making a new constructor for settlement that takes the different fields as inputs.
Also, a style note: Generally, in Java, classes should begin with a capital letter, so Settlement rather than settlement might make a better name.
You should define a townRey object then use this object to call returnStrength
townRey mytownRey = new townRey();
System.out.println(townRey.returnStrength());
I expect you want townRey to be an instance of settlement, not a subclass. Unless you want to have multiple copies of townRey. Replace the line public class townRey extends settlement with settlement townRey = new settlement(), and add a semicolon after }}. Leave everything else the same.
public class mainclss()
{
public static void main(String arg[])
{
townRey= new settlement();
//you can do sth you like
}
}
create a new class to check.DO NOT start Java with Class!It is a little difficult.
Create a separate class with main() method. Inside this method, you should create an object of townRey, in order to access the method returnStrength(). You can't access it using the class name 'townRay' if you are doing so. So Add this class with the code below:
public class MainClass {
public static void main(String[] args) {
townRey tr = new townRey();
System.out.println( tr.returnStrength () );
}
}
This worked fine with me. So you can safely use it.
NOTE: You should learn by practice to start each word in your class name with a capital letter such as Settlement and TownRey. Good Luck!

Categories