Использую JDBC для чтения и записи объектов в DB.
В одном из объектов (Coupon) есть поле типа CouponType (что является enum CouponType).
enum CouponType:
package db_package;
public enum CouponType {
RESTURANS("RESTURANS"),
ELECTRICITY("ELECTRICITY"),
FOOD("FOOD"),
HEALTH("HEALTH"),
SPORTS("SPORTS"),
CAMPING("CAMPING"),
TREVELLING("TREVELLING");
private String type;
CouponType(String type) {
this.type = type;
}
public String type() {
return type;
}
}
Когда я выполняю метод getCoupon я создаю новый купон заполняю его поля данными из DB, и возвращаю.
class CouponDBDAO() — getCoupon, creatCoupon methods:
public void createCoupon(Coupon coup) {
Statement st;
try {
st = getStatment();
if(st != null){
st.execute(SQLConstantsQuery.INSERT_INTO_COUPON_VALUES
+ "(" + coup.getId() + ",'" + coup.getTitle()
+ "','" + coup.getStartDate() + "','" + coup.getEndDate() + "',"
+ coup.getAmount() + ",'" + coup.getType() + "','" + coup.getMessage()
+ "'," + coup.getPrice() + ",'" + coup.getImage() + "');");
System.out.println("Coupon " + coup.getTitle() + " added to DB");
}else{
throw new UpdateException("The Statement is null...");
}
} catch (SQLException | UpdateException e) {
e.printStackTrace();
}
}
public Coupon getCoupon(long id) {
//Создание нового объекта Coupon для возврата
Coupon coupon = new Coupon();
ResultSet rs;
String typeFromDB;
try {
//Метод getStatment() возвращает Statment далее выполняем SQL запрос и получаем объект Coupon.
rs = getStatment().executeQuery(SQLConstantsQuery.SELECT_COUPON_BY_ID + id );
while(rs.next()){
coupon.setId(rs.getLong(SQLConstantsQuery.COUPON_ID));
coupon.setTitle(rs.getString(SQLConstantsQuery.COUPON_TITLE));
coupon.setStartDate(rs.getDate(SQLConstantsQuery.COUPON_START_DATE));
coupon.setEndDate(rs.getDate(SQLConstantsQuery.COUPON_END_DATE));
coupon.setAmount(rs.getInt(SQLConstantsQuery.COUPON_AMOUNT));
typeFromDB = rs.getString(SQLConstantsQuery.COUPON_TYPE);
CouponType ct = CouponType.valueOf(typeFromDB.toUpperCase(Locale.ENGLISH));
coupon.setType(ct);
coupon.setMessage(rs.getString(SQLConstantsQuery.COUPON_MESSAGE));
coupon.setPrice(rs.getDouble(SQLConstantsQuery.COUPON_PRICE));
coupon.setImage(rs.getString(SQLConstantsQuery.COUPON_IMAGE));
}
} catch (SQLException e) {
e.printStackTrace();
}
return coupon;
}
Все бы хорошо но когда я делаю setType то метод ждет от меня значение типа CouponType, а у меня String.
Но не беда, я делаю:
CouponType ct = CouponType.valueOf(typeFromDB.toUpperCase(Locale.ENGLISH));
и передаю ct
в метод setType.
Теперь можно запустить Main создав перед этим несколько объектов
Main class:
public class MainTest {
public static void main(String[] args) {
CouponDBDAO c = new CouponDBDAO();
Coupon coupon = new Coupon(6, "title4", "message3", "image3", 5.2, "2015-11-23", "2015-12-23", 773,
CouponType.HEALTH);
System.out.println(c.getCoupon(coupon.getId()));
}
}
class Coupon:
public class Coupon {
private long id;
private String title, message, image;
private double price;
private Date startDate, endDate;
private int amount;
private CouponType type;
protected static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-mm-dd", Locale.US);
public Coupon(){
}
public Coupon(long id, String title, String message, String image, double price,
String startDate, String endDate, int amount, CouponType type) throws ParseException {
super();
this.id = id;
this.title = title;
this.message = message;
this.image = image;
this.price = price;
this.startDate = formatter.parse(startDate);
this.endDate = formatter.parse(endDate);
this.amount = amount;
this.type = type;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getStartDate() {
return formatter.format(this.startDate);
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return formatter.format(this.endDate);
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public CouponType getType() {
return type;
}
public void setType(CouponType type) {
this.type = type;
}
@Override
public String toString() {
return "Coupon [id=" + id + ", title=" + title + ", message=" + message + ", image=" + image + ", price="
+ price + ", startDate=" + startDate + ", endDate=" + endDate + ", amount=" + amount + ", type=" + type
+ "]";
}
}
Ну и теперь самое главное что я хочу спросить, после запуска я получаю ошибку:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant db_package.CouponType.ELECTRICITY
at java.lang.Enum.valueOf(Unknown Source)
at db_package.CouponType.valueOf(CouponType.java:1)
at db_package.CouponDBDAO.getCoupon(CouponDBDAO.java:108)
at db_package.MainTest.main(MainTest.java:54)
и немогу понять по чему? Ведь есть такая константа.
Подскажите пожалуйста что не так.
Pre-requisite : Java : Enumeration Handling
Below is example of enumeration by using all implicit methods of enumeration.
Here used wrong value of enumeration as “Saturday” while using month name here that’s why causing this issue.
package enm; public class EnumTest { enum Month{JANNUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER}; enum MonthDetail{ JANNUARY("January",1), FEBRUARY("February",2), MARCH("March",3), APRIL("April",4), MAY("May",5), JUNE("June",6), JULY("July",7), AUGUST("August",8), SEPTEMBER("September",9), OCTOBER("October",10), NOVEMBER("November",11), DECEMBER("December",12); public String monthName=""; public int index; //Constructor will always private private MonthDetail(String monthName,int index) { this.monthName=monthName; this.index=index; } //Method public void showMonthDetail() { System.out.println(this.index +" : "+this.monthName); } }; public static void main(String[] args) { for(Month month:Month.values()) { //Add one because by default enum indexing start from 0 System.out.println((month.ordinal()+1) +" : "+month.name()); } //Every enum Class provide values method to get list of enums for(MonthDetail monthDetail:MonthDetail.values()) { monthDetail.showMonthDetail(); } try { MonthDetail mnth=MonthDetail.valueOf("Saturday"); } catch(Exception ex) { ex.printStackTrace(); } } }
Output
1 : JANNUARY 2 : FEBRUARY 3 : MARCH 4 : APRIL 5 : MAY 6 : JUNE 7 : JULY 8 : AUGUST 9 : SEPTEMBER 10 : OCTOBER 11 : NOVEMBER 12 : DECEMBER 1 : January 2 : February 3 : March 4 : April 5 : May 6 : June 7 : July 8 : August 9 : September 10 : October 11 : November 12 : December Exception in thread "main" java.lang.IllegalArgumentException: No enum constant enm.EnumTest.MonthDetail.Saturday at java.lang.Enum.valueOf(Enum.java:238) at enm.EnumTest$MonthDetail.valueOf(EnumTest.java:1) at enm.EnumTest.main(EnumTest.java:49)
Solutions:
Always use valid constant values to resolve this issue and while trying to call this enum.valueOf() method always handle exception so that any exception happen then your program will not terminate.
try { MonthDetail mnth=MonthDetail.valueOf("August"); } catch(Exception ex) { ex.printStackTrace(); }
To learn more on Enumeration follow below link: Java : Enumeration Handling
“Learn From Others Experience»
MyBatis version
3.5.6
Database vendor and version
PostgreSQL 12.4
PostgreSQL Driver 42.2.19
Java 11.0.8
Test case or example project
public class Mybatis { public static class History { public enum Operation { FOO, BAR } int id; int userId; Operation operation; History(int id, Operation operation) { this.id = id; this.userId = id; // Just for test this.operation = operation; } } public static void main(String[] args) throws IOException { InputStream stream = Resources.getResourceAsStream("mybatis.xml"); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(stream); try (SqlSession session = factory.openSession()) { HistoryMapper mapper = session.getMapper(HistoryMapper.class); mapper.insert(new History(1, History.Operation.FOO)); mapper.insert(new History(2, History.Operation.BAR)); session.commit(); mapper.select(); } } }
HistoryMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="rockworkx.HistoryMapper"> <select id="select" resultType="History"> SELECT history.id, history.user_id, history.operation FROM history </select> <insert id="insert" parameterType="History"> INSERT INTO history(id, user_id, operation) VALUES (#{id}, #{userId}, #{operation}) </insert> </mapper>
mybatis.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <typeAliases> <typeAlias alias="History" type="rockworkx.Mybatis$History" /> </typeAliases> <environments default="postgres"> <environment id="postgres"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="org.postgresql.Driver" /> <property name="url" value="jdbc:postgresql://localhost:5432/postgres" /> <property name="username" value="postgres" /> <property name="password" value="postgres" /> </dataSource> </environment> </environments> <mappers> <mapper resource="HistoryMapper.xml" /> </mappers> </configuration>
Steps to reproduce
When I use an underscored column user_id
together with a java Enum type, Mybatis throws a IllegalArgumentException
with message No enum constant
.
But if I get rid of the underscored column user_id
, everything goes well.
And I also confused with the exception message:
Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'user_id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant rockworkx.Mybatis.History.Operation.1
Why the user_id
column is related to the Enum type Operation
?
I guess that some implementation details dealing with underscored column or Enum type may be wrong.
Expected result
Actual result
Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'user_id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant rockworkx.Mybatis.History.Operation.1
### The error may exist in HistoryMapper.xml
### The error may involve rockworkx.HistoryMapper.select
### The error occurred while handling results
### SQL: SELECT history.id, history.user_id, history.operation FROM history
### Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'user_id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant rockworkx.Mybatis.History.Operation.1
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:149)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:152)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85)
at com.sun.proxy.$Proxy4.select(Unknown Source)
at rockworkx.Mybatis.main(Mybatis.java:40)
Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'user_id' from result set. Cause: java.lang.IllegalArgumentException: No enum constant rockworkx.Mybatis.History.Operation.1
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:87)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createUsingConstructor(DefaultResultSetHandler.java:710)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createByConstructorSignature(DefaultResultSetHandler.java:693)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:657)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:630)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.getRowValue(DefaultResultSetHandler.java:397)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValuesForSimpleResultMap(DefaultResultSetHandler.java:354)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleRowValues(DefaultResultSetHandler.java:328)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSet(DefaultResultSetHandler.java:301)
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:194)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:89)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
... 7 more
Caused by: java.lang.IllegalArgumentException: No enum constant rockworkx.Mybatis.History.Operation.1
at java.base/java.lang.Enum.valueOf(Enum.java:240)
at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:49)
at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:26)
at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:85)
... 24 more
Расскажите, что это за ошибка и как ее исправить?
Поймал такую вот ошибку «java: No enum constant javax.lang.model.element.Modifier.SEALED «
Не могу понять, что это за ошибка, откуда взялась, что с ней делать? В сети информации мало, решил тут спросить
-
Вопрос задан
-
176 просмотров
Пригласить эксперта
Похоже, у вас версия java до 17 :
...
/**
* The modifier {@code sealed}
* @since 17
*/
SEALED,
...
Обнови JDK до 17. Да и скоро выйдет JDK 21 (в сентябре 2023 года).
-
Показать ещё
Загружается…
21 сент. 2023, в 16:00
100000 руб./за проект
21 сент. 2023, в 15:53
10000 руб./за проект
21 сент. 2023, в 15:48
5000 руб./за проект
Минуточку внимания
Answer by Keanu Haley
java.lang.IllegalArgumentException: No enum constant,A call to the method getByName(«columnHeadings») is throwing java.lang.IllegalArgumentException: No enum const class labware.web.component.limsgrid.PropName.columnHeadings but if I replace this method with the following code it just works .,
Questions
,The enum’s «builtin» (implicitly declared) valueOf(String name) method will look up an enum constant with that exact name. If your input is «columnHeadings», you have (at least) three choices:
1.Create companion object with parsing method.
enum class CarsType {
@Json(name = "SMALL")
SMALL,
@Json(name = "BIG")
BIG;
companion object {
fun nullableValueOf(name: String?) = when (name) {
null -> null
else -> valueOf(name)
}
}
}
2. In Parcerable read place use it like this
data class CarData(
val carId: String? = null,
val carType: CarsType?,
val data: String?
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
CarsType.nullableValueOf(parcel.readString()),
parcel.readString())
Answer by Capri Huang
The enum’s «builtin» (implicitly declared) valueOf(String name) method will look up an enum constant with that exact name. If your input is «columnHeadings», you have (at least) three choices:,Forget about the naming conventions for a bit and just name your constants as it makes most sense: enum PropName { contents, columnHeadings, …}. This is obviously the most convenient.,Enum.valueOf() only checks the constant name, so you need to pass it «COLUMN_HEADINGS» instead of «columnHeadings». Your name property has nothing to do with Enum internals.,Implement your own lookup method instead of the builtin valueOf to find the corresponding constant for an input. This makes most sense if there are multiple possible mappings for the same set of constants.
Enum.valueOf()
only checks the constant name, so you need to pass it "COLUMN_HEADINGS"
instead of «columnHeadings». Your name
property has nothing to do with Enum internals.
Enum.valueOf()
Enum.valueOf()
only checks the constant name, so you need to pass it "COLUMN_HEADINGS"
instead of «columnHeadings». Your name
property has nothing to do with Enum internals.
"COLUMN_HEADINGS"
Enum.valueOf()
only checks the constant name, so you need to pass it "COLUMN_HEADINGS"
instead of «columnHeadings». Your name
property has nothing to do with Enum internals.
name
Answer by Pablo Randolph
Is there a problem with this formulation?,Any ideas as to what I am doing wrong here ?,To address the questions/concerns in the comments:,The reason is that you always have the possibility to override an in-class initializer list in the constructor. So I guess that in the end, it could be very confusing.
This question is basically an extension of my previous question . I asked the previous question to be sure that the Enum constants are populated when the class loads . Here’s is my class again with the addition of a simple method getByName
:
public enum PropName {
CONTENTS("contents"),
USE_QUOTES("useQuotes"),
ONKEYDOWN("onkeydown"),
BROWSER_ENTIRE_TABLE("browseEntireTable"),
COLUMN_HEADINGS("columnHeadings"),
PAGE_SIZE("pageSize"),
POPUP_TITLE("popupTitle"),
FILTER_COL("filterCol"),
SQL_SELECT("sqlSelect"),
;
private String name;
private PropName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static PropName getByName(String name){
return PropName.valueOf(name);
}
}
A call to the method getByName("columnHeadings")
is throwing java.lang.IllegalArgumentException: No enum const class labware.web.component.limsgrid.PropName.columnHeadings
but if I replace this method with the following code it just works .
public static PropName getByName(String name){
for(PropName prop : values()){
if(prop.getName().equals(name)){
return prop;
}
}
throw new IllegalArgumentException(name + " is not a valid PropName");
}
Answer by Deacon Ahmed
What is the reason for java.lang.IllegalArgumentException: No enum const class even though iterating through values() works just fine?, How to cast a variable to certain runtime type got from TypeCast in Scala Scala | 1 week ago , fastd/migration 使用 PHP | 2 months ago , elao/form-bundle Installation PHP | 2 months ago
1.public enum PropName {2.3. CONTENTS("contents"),4. USE_QUOTES("useQuotes"),5. ONKEYDOWN("onkeydown"),6. BROWSER_ENTIRE_TABLE("browseEntireTable"),7. COLUMN_HEADINGS("columnHeadings"),8. PAGE_SIZE("pageSize"),9. POPUP_TITLE("popupTitle"),10. FILTER_COL("filterCol"),11. SQL_SELECT("sqlSelect"),12. ;13.14. private String name;15.16. private PropName(String name) {17. this.name = name;18. }19.20. public String getName() {21. return name;22. }23.24. public static PropName getByName(String name){25. return PropName.valueOf(name);26. }27.}28.
Answer by Gianni O’Neal
There are several ways to solve the same problem. Some are better than others.,Here’s the enum we will be using in our examples. Let’s pick a more complex enum to also showcase looking an enum up by another field.,The following all work by using an index in the form of a Map. There are some minor differences as well as boilerplate concerns.,This exact same approach can be used for additional fields of the enum. It’s not uncommon to want to look up an enum by its display name or some other property.
Here’s the enum we will be using in our examples. Let’s pick a more complex enum to also showcase looking an enum up by another field.
public enum CardColor {
RED,
BLACK,
;
}
// Jackson annotation to print the enum as an Object instead of the default name.
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum CardSuit {
// Unicode suits - https://en.wikipedia.org/wiki/Playing_cards_in_Unicode
SPADE("Spade", String.valueOf((char) 0x2660), CardColor.BLACK),
HEART("Heart", String.valueOf((char) 0x2665), CardColor.RED),
DIAMOND("Diamond", String.valueOf((char) 0x2666), CardColor.RED),
CLUB("Club", String.valueOf((char) 0x2663), CardColor.BLACK),
;
private String displayName;
private String symbol;
private CardColor color;
private CardSuit(String displayName, String symbol, CardColor color) {
this.displayName = displayName;
this.symbol = symbol;
this.color = color;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public CardColor getColor() {
return color;
}
public void setColor(CardColor color) {
this.color = color;
}
Using Enum.valueOf
is great when you know the input is valid. However, if you pass in an invalid name, an exception will be thrown. In some cases, this is fine. Oftentimes. we would prefer to just ignore it and return null.
log.debug("Running valueOf");
for (String name : names) {
try {
log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.valueOf(name)));
} catch (Exception ex) {
log.warn("Exception Thrown", ex);
}
}
2017-02-22 14:46:38.556 [main] DEBUG c.s.examples.common.EnumLookup - Running valueOf
2017-02-22 14:46:38.804 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.806 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.808 [main] WARN c.s.examples.common.EnumLookup - Exception Thrown
java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
at java.lang.Enum.valueOf(Enum.java:238)
at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:154)
This bad practice is most commonly made by beginners. Exceptions shouldn’t be used for control flow and could have some performance implications. Don’t be lazy. Do it the right way.
/*
* Please don't do this! Using try / catch for
* control flow is a bad practice.
*/
public static CardSuit trycatchValueOf(String name) {
try {
return CardSuit.valueOf(name);
} catch (Exception ex) {
log.warn("Exception Thrown", ex);
return null;
}
}
log.debug("Running trycatchValueOf");
for (String name : names) {
log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.trycatchValueOf(name)));
}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running trycatchValueOf
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.809 [main] WARN c.s.examples.common.EnumLookup - Exception Thrown
java.lang.IllegalArgumentException: No enum constant com.stubbornjava.examples.common.EnumLookup.CardSuit.Missing
at java.lang.Enum.valueOf(Enum.java:238)
at com.stubbornjava.examples.common.EnumLookup$CardSuit.valueOf(EnumLookup.java:1)
at com.stubbornjava.examples.common.EnumLookup$CardSuit.trycatchValueOf(EnumLookup.java:89)
at com.stubbornjava.examples.common.EnumLookup.main(EnumLookup.java:171)
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
This approach is also quite common (see here), but at least the authors know not to try/catch the exceptions. What is wrong with this approach? It’s iterating over all enums until it finds the matching enum or returning null — with a worst case of N, where N is the number of enum values. Some may argue this is being nitpicky and it’s premature optimization. However, data structures and algorithms are CS fundamentals. It’s not that much effort to use a Map instead of iterating a collection. Will it drastically improve performance? No, but it is a good habbit. When interviewing a candidate for a job, would you be happy with a linear complexity search algorithm? You shouldn’t let this code review pass in that case.
/*
* Please don't do this! It is inefficient and it's
* not very hard to use Guava or a static Map as an index.
*/
public static CardSuit iterationFindByName(String name) {
for (CardSuit suit : CardSuit.values()) {
if (name.equals(suit.name())) {
return suit;
}
}
return null;
}
log.debug("Running iteration");
for (String name : names) {
log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.iterationFindByName(name)));
}
2017-02-22 14:46:38.808 [main] DEBUG c.s.examples.common.EnumLookup - Running iteration
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
What is the correct data structure to use for quick lookups of fixed size? A HashMap. Now with a little extra boilerplate, we have a much more efficient lookup as long as we have a good hash function. A bit more verbose, and it would be nice if there was a way to reduce the boilerplate.
private static final Map<String, CardSuit> nameIndex =
Maps.newHashMapWithExpectedSize(CardSuit.values().length);
static {
for (CardSuit suit : CardSuit.values()) {
nameIndex.put(suit.name(), suit);
}
}
public static CardSuit lookupByName(String name) {
return nameIndex.get(name);
}
log.debug("Running lookupByName");
for (String name : names) {
log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.lookupByName(name)));
}
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByName
2017-02-22 14:46:38.809 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.810 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
This is such a common use case that our friends over at Google made a very clean and boilerplate-free solution for us. Under the hood, it even uses WeakReferences and WeakHashMaps. Basically, this code will create a global static map keyed on the Enum’s class name and use it for lookups.
public static CardSuit getIfPresent(String name) {
return Enums.getIfPresent(CardSuit.class, name).orNull();
}
log.debug("Running Guava getIfPresent");
for (String name : names) {
log.debug("looking up {} found {}", name, Json.serializer().toString(CardSuit.getIfPresent(name)));
}
2017-02-22 14:46:38.813 [main] DEBUG c.s.examples.common.EnumLookup - Running Guava getIfPresent
2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up SPADE found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.814 [main] DEBUG c.s.examples.common.EnumLookup - looking up HEART found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up DIAMOND found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up CLUB found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Same approach as above, but indexed on the display name instead of the enum name.
private static final Map<String, CardSuit> displayNameIndex =
Maps.newHashMapWithExpectedSize(CardSuit.values().length);
static {
for (CardSuit suit : CardSuit.values()) {
displayNameIndex.put(suit.getDisplayName(), suit);
}
}
public static CardSuit lookupByDisplayName(String name) {
return displayNameIndex.get(name);
}
log.debug("Running lookupByDisplayName");
for (String displayName : displayNames) {
log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayName(displayName)));
}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayName
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.815 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
We can’t leverage Guava here, since it would be difficult to create unique global keys for the static index. However, that doesn’t mean we can’t make our own helpers!
public class EnumUtils {
public static <T, E extends Enum<E>> Function<T, E> lookupMap(Class<E> clazz, Function<E, T> mapper) {
@SuppressWarnings("unchecked")
E[] emptyArray = (E[]) Array.newInstance(clazz, 0);
return lookupMap(EnumSet.allOf(clazz).toArray(emptyArray), mapper);
}
public static <T, E extends Enum<E>> Function<T, E> lookupMap(E[] values, Function<E, T> mapper) {
Map<T, E> index = Maps.newHashMapWithExpectedSize(values.length);
for (E value : values) {
index.put(mapper.apply(value), value);
}
return (T key) -> index.get(key);
}
}
Now we have a fairly boilerplate-free generic solution.
private static final Function<String, CardSuit> func =
EnumUtils.lookupMap(CardSuit.class, e -> e.getDisplayName());
public static CardSuit lookupByDisplayNameUtil(String name) {
return func.apply(name);
}
log.debug("Running lookupByDisplayNameUtil");
for (String displayName : displayNames) {
log.debug("looking up {} found {}", displayName, Json.serializer().toString(CardSuit.lookupByDisplayNameUtil(displayName)));
}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - Running lookupByDisplayNameUtil
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Spade found {"displayName":"Spade","symbol":"♠","color":"BLACK"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Heart found {"displayName":"Heart","symbol":"♥","color":"RED"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Diamond found {"displayName":"Diamond","symbol":"♦","color":"RED"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Club found {"displayName":"Club","symbol":"♣","color":"BLACK"}
2017-02-22 14:46:38.816 [main] DEBUG c.s.examples.common.EnumLookup - looking up Missing found null
Answer by Collins Erickson
Below is example of enumeration by using all implicit methods of enumeration.Here used wrong value of enumeration as “Saturday” while using month name here that’s why causing this issue.,Pre-requisite : Java : Enumeration Handling,To learn more on Enumeration follow below link: Java : Enumeration Handling,Solutions:Always use valid constant values to resolve this issue and while trying to call this enum.valueOf() method always handle exception so that any exception happen then your program will not terminate.
package enm;
public class EnumTest {
enum Month{JANNUARY,FEBRUARY,MARCH,APRIL,MAY,JUNE,JULY,AUGUST,SEPTEMBER,OCTOBER,NOVEMBER,DECEMBER};
enum MonthDetail{
JANNUARY("January",1),
FEBRUARY("February",2),
MARCH("March",3),
APRIL("April",4),
MAY("May",5),
JUNE("June",6),
JULY("July",7),
AUGUST("August",8),
SEPTEMBER("September",9),
OCTOBER("October",10),
NOVEMBER("November",11),
DECEMBER("December",12);
public String monthName="";
public int index;
//Constructor will always private
private MonthDetail(String monthName,int index)
{
this.monthName=monthName;
this.index=index;
}
//Method
public void showMonthDetail()
{
System.out.println(this.index +" : "+this.monthName);
}
};
public static void main(String[] args) {
for(Month month:Month.values())
{
//Add one because by default enum indexing start from 0
System.out.println((month.ordinal()+1) +" : "+month.name());
}
//Every enum Class provide values method to get list of enums
for(MonthDetail monthDetail:MonthDetail.values())
{
monthDetail.showMonthDetail();
}
try
{
MonthDetail mnth=MonthDetail.valueOf("Saturday");
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
Answer by Adelaide Fields
Special case of interpolating closure expressions,resolves the parent/child relationship for nested nodes, involving two other strategies:,Statements and expressions,Once you’ve written the class, using it is just a matter of redefining the groovydoc task:
// a standalone single line comment
println "hello" // a comment till the end of the line
Answer by Jessie Sharp
Hibernate supports the mapping of Java enums as basic value types in a number of different ways.,Hibernate supports three types of configurations within OSGi.,The mapping between the standard SQL Date/Time types and the supported Java 8 Date/Time class types looks as follows;,See the Hibernate Integrations Guide for more details on developing custom value type mappings.
create table Contact (
id integer not null,
first varchar(255),
last varchar(255),
middle varchar(255),
notes varchar(255),
starred boolean not null,
website varchar(255),
primary key (id)
)
Answer by Zara Frazier
To configure the check:
,To configure the check:,
To configure the default check:
,
To configure the default check:
int[] a = new int[]
{
1,
2,
3,
};