I want the last enum to have a different value in one of the variables:
private enum thing {
thing0(0),
thing1(1),
thing2(2);
int index;
String s;
private thing(int index) {
this.index = index;
s = index == values().length - 1 ? "b" : "a";
}
}
This doesn't work; you can't call values() in the constructor. Is there another way?
In general, don't rely on the declaration order of the enum values. Item 35 in Effective Java 3rd Ed, "Use instance fields instead of ordinals", explains why. (Note that whilst you are using an instance field for s, its value depends on the ordinal.)
If you want a particular value to have a particular property, pass it in as a constructor parameter.
private enum thing {
thing0(0),
thing1(1),
thing2(2, "b");
int index;
String s;
private thing(int index) {
this(index, "a");
}
private thing(int index, String s) {
this.index = index;
this.s = s;
}
}
If you really do want it to be checking for the last value in the enum, an alternative way to do this is with a getter. Initialize a static final field in the enum to be the last value:
// Invokes `values()` twice, but meh, it's only executed once.
private static final thing LAST = values()[values().length-1];
Then check in a getter:
String s() {
return this == LAST ? "b" : "a";
}
There is no need to maintain an index that always matches the ordinal of the enum constant. Further, you can’t rely on the values() array in the constructor as it is supposed to contain the already constructed instances. But to determine, how many constants exist, it is enough to count the associated fields.
public enum Thing {
thing0,
thing1,
thing2;
final String s;
Thing() {
this.s = ordinal() == numConstants() - 1? "b": "a";
}
#Override
public String toString() {
return name() + "(index = " + ordinal() + ", s = " + s + ")";
}
private static int NUM_CONSTANTS;
private static int numConstants() {
int i = NUM_CONSTANTS;
if(i != 0) return i;
for(Field f: Thing.class.getDeclaredFields()) if(f.isEnumConstant()) i++;
NUM_CONSTANTS = i;
return i;
}
}
So System.out.println(EnumSet.allOf(Thing.class)); prints
[thing0(index = 0, s = a), thing1(index = 1, s = a), thing2(index = 2, s = b)]
Note that numConstants() caches the value in NUM_CONSTANTS which is safe as the private method is only invoked within the class initializer. We can’t use a static final variable here, as all custom class initialization will be done after the enum constants have been constructed.
Related
I am trying to create a enum with values 1,-1,0 but while mapping the data unknown Ordinal value for -1 is coming. Below is the piece of code for the enum . How the enum can be use to retrieve the ordinal value for -1
#RequiredArgsConstructor
public enum Number {
MULTIPLE(0, -1, "MULTIPLE"),
ZERO(1, 0, "ZERO"),
ONE(2, 1, "ONE");
private static final Map<Integer, Number> DOCUMENT_CARDINALITY_ID = Arrays.stream(values())
.collect(Collectors.toMap(Number :: intValue, Function.identity()));
private static final Map<String, Number> DOCUMENT_CARDINALITY_BY_CODE = Arrays.stream(values())
.collect(Collectors.toMap(Number :: toString, Function.identity()));
private final int value;
private final int id;
private final String code;
public static Number of(int id) {
isTrue(DOCUMENT_CARDINALITY_ID.containsKey(id), "the id " + id + " is not valid!");
return DOCUMENT_CARDINALITY_ID.get(id);
}
public static Number of(String code) {
notNull(code, "the code is null!");
isTrue(DOCUMENT_CARDINALITY_BY_CODE.containsKey(code), "the code " + code + " is not valid!");
return DOCUMENT_CARDINALITY_BY_CODE.get(code);
}
public int intValue() {
if (id == -1) {
return 0;
} else if (id == 0) {
return 1;
} else {
return 2;
}
}
#Override
public String toString() {
return code;
}
}
You cannot set the ordinal value of an Enum. The ordinal value is set based upon its position during Enum declaration. In this case, the ordinals might look like
0 MULTIPLE
1 ZERO
2 ONE
See this previous post for more details. Also your spring error is occurring outside of this class and so, I have no idea what would be triggering it
I'm still a little confused with regards to the difference between static and dynamic. From what I know dynamic uses object while static use type and that dynamic is resolved during runtime while static is during compile time. so shouldn't this.lastName.compareTo(s1.lastName) use dynamic binding instead?
key.compareTo(list[position-1]) use dynamic binding
public static void insertionSort (Comparable[] list)
{
for (int index = 1; index < list.length; index++)
{
Comparable key = list[index];
int position = index;
while (position > 0 && key.compareTo(list[position-1]) < 0) // using dynamic binding
{
list[position] = list[position-1];
position--;
}
list[position] = key;
}
}
Why does (this.lastName.compareTo(s1.lastName)) use static binding?
private String firstName;
private String lastName;
private int totalSales;
#Override
public int compareTo(Object o) {
SalePerson s1 = (SalePerson)o;
if (this.totalSales > s1.getTotalSales())
{
return 1;
}
else if (this.totalSales < s1.getTotalSales())
{
return -1;
}
else //if they are equal
{
return (this.lastName.compareTo(s1.lastName)); //why is this static binding??
}
}
Your question isn't complete and doesn't include all relevant the code. However this is the basic difference between the different bindings
Java has both static and dynamic binding. Binding refers to when variable is bound to a particular data type.
Static/Early binding is done at compile time for: private, final and static methods and variables. And also for overloaded methods
Dynamic/late binding is done at runtime for: methods which can be overriden methods. This is what enables polymorphic behaviour at runtime.
To further demonstrate this point have a look at this code and see if you can determine when it would be early and late binding:
/* What is the output of the following program? */
public class EarlyLateBinding {
public boolean equals(EarlyLateBinding other) {
System.out.println("Inside of overloaded Test.equals");
return false;
}
public static void main(String[] args) {
Object t1 = new EarlyLateBinding(); //1
Object t2 = new EarlyLateBinding(); //2
EarlyLateBinding t3 = new EarlyLateBinding(); //3
Object o1 = new Object();
Thread.currentThread().getStackTrace();
int count = 0;
System.out.println(count++);
t1.equals(t2);//n
System.out.println(count++);
t1.equals(t3);//n
System.out.println(count++);
t3.equals(o1);
System.out.println(count++);
t3.equals(t3);
System.out.println(count++);
t3.equals(t2);
}
}
Answer:
++ is after the count and hence the result returned is the 0 before incrementing it. Hence starts with 0 and proceeds as you expect.
The only scenario where the equals methods of EarlyLateBinding object
is actually invoked is is statement 3.
This is because the equals method is overloaded (Note: the different
method signature as compared to the object class equals)
Hence the type EarlyLateBinding is bound to the variable t3 at
compile time.
.
in this code
public static void insertionSort (Comparable[] list)
{
for (int index = 1; index < list.length; index++)
{
Comparable key = list[index];
int position = index;
while (position > 0 && key.compareTo(list[position-1]) < 0)
{
list[position] = list[position-1];
position--;
}
list[position] = key;
}
}
key can be anything that implements the Comparable interface so in the compile time compiler doesn't know the exact type so type is resolved in the runtime by using the object that key referring to.
But in this code,
#Override
public int compareTo(Object o) {
SalePerson s1 = (SalePerson)o;
if (this.totalSales > s1.getTotalSales())
{
return 1;
}
else if (this.totalSales < s1.getTotalSales())
{
return -1;
}
else //if they are equal
{
return (this.lastName.compareTo(s1.lastName));
}
}
compiler knows the type of the s1 so it use the static binding
I have an object with fields of different types, mainly String, Float, Integer.
I need to write a method to check an array of such objects, whether specific fields, identified by a certain string identifiers, are not null and not empty.
For example, I have the following fields:
String field1;
Integer field2;
String field3;
and an identifiers:
String IDENTIFIER_FIELD_1 = "IDENTIFIER_1";
String IDENTIFIER_FIELD_2 = "IDENTIFIER_2";
If I pass an ArrayList<String> with IDENTIFIER_FIELD_1 to my method, I want to check field1 only, if I pass an ArrayList<String> with IDENTIFIER_FIELD_1 and IDENTIFIER_FIELD_2, I would like to check both field2 and field2.
Is there any effective way in Java to do such checks for an array of objects? The only solution I come up with is to check every field using string comparison but that wouldn't be effective at all.
You could use a bit of reflection, it might be an "overkill" tho. There is a flaw in this method, you need to know the exact names of variables, but I believe you have them.
public class TestObject {
//Some fields.
private int firstInt;
private int secondInt;
private String firstString;
public TestObject(int firstInt, int secondInt, String firstString) {
this.firstInt = firstInt;
this.secondInt = secondInt;
this.firstString = firstString;
}
public void checkForNulls(String... fieldsToSearch) throws IllegalArgumentException, IllegalAccessException {
boolean isValid = true;
//Here we retrieve all the fields we need from our class.
for (String fieldName : fieldsToSearch) {
//Here is the method to get a field by name.
try {
Field field = this.getClass().getDeclaredField(fieldName);
//Change access modifier so we can get the value.
field.setAccessible(true);
//Get the field value of this instance.
if (field.get(this) == null) {
isValid = false;
System.out.println("Fix him! Field " + field.getName() + " equals null!");
}
} catch (Exception e) {
//There can be no field with such name, you need to do something here.
}
}
if (isValid) {
System.out.println("This objects fields are fine.");
}
}
}
And now the main method:
public class Test {
//Names of the fields, you actually need to know them.
public static final String FIRST_INT_INDENTIFIER = "firstInt";
public static final String SECOND_INT_INDENTIFIER = "secondInt";
public static final String FIRST_STRING_INDENTIFIER = "firstString";
public static void main(String[] args) {
TestObject[] testArray = new TestObject[10];
//Fill the array with some objects.
for (int i = 0; i < testArray.length; i++) {
testArray[i] = new TestObject(i, i * 2, "Number: " + i);
if (i % 3 == 0) {
testArray[i] = new TestObject(i, i * 2, null);
}
}
//Check the array of our objects.
for (int i = 0; i < testArray.length; i++) {
try {
testArray[i].checkForNulls(FIRST_INT_INDENTIFIER, FIRST_STRING_INDENTIFIER);
} catch (Exception e) {
//Some exception handling
}
}
}
}
You could use contains method like:
if (mylist.contains("field1") && myList.contains("field2")) {
System.out.println("Found both identifier");
}
I would put a method inside the object, something like:
public boolean isPopulated(String key){ // or int key if you're more interested in efficiency than clarity
switch(key){
case "field1":
if (field1 != null && !field1.equals("")) return true;
return false;
break;
case "field2":
etc
That way you can define for each field what 'empty' means.
Then stating the obvious, your checking method would look like (assuming you went with Integer fields rather than Strings)
public boolean areAllPopulated(ArrayList<MyObject> objects, ArrayList<Integer> fields) {
for (Integer field : fields){
for (MyObject object : objects){
if (object.isPopulated(field) == false){
return false;
}
}
}
return true;
}
If you're worried about the cost of String comparison, you could create a HashMap of fieldNames to fieldIntegers somewhere and convert the ArrayList of
Strings to an ArrayList of Integers at the start of the checking method, which would save you most of the String comparison penalty.
java.lang.String is declared as final, however are there any mechanisms available legitimate or otherwise to extend it and replace the equals(String other) method?
No, absolutely not. If you want some "other" kind of string, create another type which might contain a string:
public final class OtherString {
private final String underlyingString;
public OtherString(String underlyingString) {
this.underlyingString = underlyingString;
}
// Override equals however you want here
}
I guess the closest you can come is making some class that implements CharSequence. Most JDK string manipulation methods accept a CharSequence. StringBuilder for example. Combined with a good implementation of toString(), the various methods of String and valueOf(), you can come pretty close to a natural substitute.
Now, there is a way. With manifold it's possible to extend every Java Class. Here is an example for String:
package extensions.java.lang.String;
import manifold.ext.api.*;
#Extension
public class MyStringExtension {
public static void print(#This String thiz) {
System.out.println(thiz);
}
#Extension
public static String lineSeparator() {
return System.lineSeparator();
}
}
Can than be used as follow:
String name = "Manifold";
name.print();
String.lineSeparator();
Another example can be found here: https://jaxenter.com/manifold-code-generator-part-2-151762.html
Notice, that manifold is still alpha.
You cannot extend a class that is marked as final. You can use composition to either put a String object inside or you can hand roll your own version. This can be accomplished via character arrays and the other magic that goes into creating String classes.
It is not possible to directly inherit String class as it is final. Also wrapper classes java.lang.Integer, java.lang.Float, etc... are final.
I wrote a simple Strings class that mimics java.lang.String and can be extended. This is just to demonstrate the core implementation requirements behind String are not "mysterious" or "complicated". And, you can use it to do things like create a password extension and manage strings more effectively.
Needs:
native call to big-endian. (see private static native boolean
isBigEndian();)
other String methods.
package com.paintedintel.util;
import java.nio.charset.StandardCharsets;
/**
*
* #author David Urry
* #date 2/8/2020
*
* Strings is a light weight string implementation based on StringUTF16.
* It's sole purpose is to create a system where strings can be extended
* so that the type of string can be extended without the weight of carrying
* extra object references.
*
* Strings extension is important for 2 reasons:
* 1) The extra object reference slows the code down by a factor of 50% making
* a 10X speed improvement only 5X. As the object of looking at/comparing and
* otherwise managing strings is expensive.
* 2) The code understanding benefits greatly from understanding the type of string
* you are working with (Name, Value, Field, InitValue, Comment...). The constant
* evaluation of List<String> for example is greatly simplified when observing
* List<Field> instead.
*
* This problem was also greatly simplified by working with Type, Domain, Datum,
* StreamDomain, StreamCase and other objects as complex objects.
*/
public class Strings {
final byte[] value;
/** Cache the hash code for the string */
private int hash; // Default to 0
protected Strings(String value){
if (value != null) {
this.value = value.getBytes();
this.hash = value.hashCode();
} else {
this.value = new byte[0];
this.hash = 0;
}
}
Strings(byte[] value){
this.value = value;
this.hash = Strings.hashCode(value);
}
#Override
public String toString() {
return new String(value, StandardCharsets.UTF_8);
}
public String str() {
return toString();
}
public boolean equals(String str) {
return (str == null)?((value == null || this.length() == 0)?true:false):str.hashCode() == value.hashCode();
}
public boolean eq(String str) {
return equals(str);
}
byte[] getBytes() {
return value;
}
int getHash() {
return hash;
}
public int length() {
return value.length >> 1;
}
/**
* this is based on StringUTF16
* #param value
* #return
*/
synchronized public static int hashCode(byte[] value) {
int h = 0;
int length = value.length >> 1;
for (int i = 0; i < length; i++) {
h = 31 * h + getChar(value, i);
}
return h;
}
// intrinsic performs no bounds checks
synchronized static char getChar(byte[] val, int index) {
assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
index <<= 1;
return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
((val[index] & 0xff) << LO_BYTE_SHIFT));
}
//private static native boolean isBigEndian();
// private static boolean isBigEndian() {
// //as of 2018 there are no major BigEndian systems left.
// // This is because it's less processing to convert & work with
// // Little-Endian.
// return false;
// }
static final int HI_BYTE_SHIFT = 0;
static final int LO_BYTE_SHIFT = 8;
// static {
// if (isBigEndian()) {
// HI_BYTE_SHIFT = 8;
// LO_BYTE_SHIFT = 0;
// } else {
// HI_BYTE_SHIFT = 0;
// LO_BYTE_SHIFT = 8;
// }
// }
synchronized public static int length(byte[] value) {
return value.length >> 1;
}
}
Does Java allow something like good ol' C or even C# in the sense that you can define an enum with fields that grow in value automatically, and start at an optionally given value?
E.g.
In C or C#:
enum Foo { A = 10, B, C, D = 5000, E, Fish };
Yields A = 10, B = 11, C = 12, D = 5000, E = 5001, Fish = 5002.
In Java you can't specify the ordinal values explicitly at all. They always autoincrement, from 0, with no control over it.
If you want other custom values, you need to put them in constructor calls and store them yourself. You can get autoincrement, but it's icky as heck:
import java.util.EnumSet;
// Please don't ever use this code. It's here so you can point and laugh.
enum Foo
{
A(10), B, C, D(5000), E, Fish;
private static int nextValue;
private int value;
private Foo()
{
this(Counter.nextValue);
}
private Foo(int value)
{
this.value = value;
Counter.nextValue = value + 1;
}
public int getValue()
{
return value;
}
private static class Counter
{
private static int nextValue = 0;
}
}
public class Test
{
public static void main(String[] args)
{
for (Foo foo : EnumSet.allOf(Foo.class))
{
System.out.println(foo.name() + " " +
foo.ordinal() + " " +
foo.getValue());
}
}
}
Note the need for the nested class, because you can't access static fields within an enum constructor. Ick, ick, ick. Please don't do this.
This is a design choice of Java Enums to not support to change the ordinal values. Basically, they are not stable enough to depend on them. If you change the position of B and C in your example clients depending on the ordinal values are broken. This may happen unintentionally.
The problem is described in Effective Java Item 31: Use instance field instead of ordinals.
You can emulate the behavior in a stable manner:
enum X{
A(10), B(A), C(B), D(5000), E(D), F(E);
private final int value;
X(int value){
this.value = value;
}
X(X preceding){
this.value = preceding.getValue() + 1;
}
public int getValue() {
return value;
}
#Override
public String toString() {
return this.name() + "(" + this.value + ")";
}
static {
Set<Integer> values = new HashSet<Integer>();
for(X x : X.values()) values.add(x.value);
assert(values.size() == X.values().length); //no duplicates
}
}
With this definition you may change the order of the values without breaking clients.
Calling for(X x : X.values()) System.out.println(x); returns:
A(10)
B(11)
C(12)
D(5000)
E(5001)
F(5002)