static final Date field in a java class

ぐ巨炮叔叔 提交于 2020-08-25 05:00:10

问题


We've a public static util method which can parse a string and return a Date object, but it also throws ParseException in case the string parsed cannot be converted to a Date object.

Now, in another class I would like to have a static final Date initialized to a value using the util method described above. But given that the util method throws ParseException, this is not allowed.

This is what I want to do, which is not allowed

public static final MY_DATE = Util.getDateFromString('20000101');

What is the recommended way to keep this Date field 'final'?


回答1:


Well you could use a static initializer block:

public static final Date MY_DATE;

static {
    try {
       MY_DATE = Util.getDateFromString("20000101");
    } catch (ParseException e) {
       // Whatever you want to do here. You might want to throw
       // an unchecked exception, or you might want to use some fallback value.
       // If you want to use a fallback value, you'd need to use a local
       // variable for the result of parsing, to make sure you only have a
       // single assignment to the final variable.
    }
}

However, I would advise against this. Date is a mutable type - exposing it via a public static final variable is a bad idea.

As of Java 8, the java.time package is the most appropriate to use for almost all date/time work, where you'd write:

public static final LocalDate START_OF_JANUARY_2000 = LocalDate.of(2000, 1, 1);

Prior to Java 8, I'd recommend that you use Joda Time which has many immutable date/time types - and is a thoroughly better library for working with dates and times. It looks like you'd want:

public static final LocalDate START_OF_JANUARY_2000 = new LocalDate(2000, 1, 1);

Note that even if you do decide to go with java.util.Date, it doesn't make much sense to parse the string in my view - you know the values numerically, so why not just supply them that way? If you haven't got a suitable method to construct a Date from a year / month / day (presumably applying an appropriate time zone) then you could easily write one.




回答2:


OMG! I finally get to out-do Jon Skeet with a better, more elite, more elegant answer!

One neat way is to use an anonymous class, with an instance block, like this:

public static final Date MY_DATE = new Date() {{
    try {
        setTime(Util.getDateFromString("20000101").getTime());
    } catch (ParseException e) {
        throw new RuntimeException(e);
    }
}};

This works because (remarkably) java.util.Date is not immutable!

To make the Date immutable, and therefore more acceptable design-wise, override the setter methods too:

public static final Date MY_DATE = new Date() {{
        try {
            super.setTime(Util.getDateFromString("20000101").getTime());
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
    // Formatted for brevity :)
    @Override public void setYear(int year) { throw new UnsupportedOperationException();}
    @Override public void setMonth(int month) {throw new UnsupportedOperationException();}
    @Override public void setDate(int date) {throw new UnsupportedOperationException();}
    @Override public void setHours(int hours) {throw new UnsupportedOperationException();}
    @Override public void setMinutes(int minutes) {throw new UnsupportedOperationException();}
    @Override public void setSeconds(int seconds) {throw new UnsupportedOperationException();}
    @Override public void setTime(long time) {throw new UnsupportedOperationException();}
};



回答3:


Another way, if you're sure you won't actually get the declared exception, is to create another method, either locally or in Util, that wraps the ParseException in an unchecked exception, like this:

public static final Date MY_DATE = getDateFromStringWithoutExploding("20000101");

private static Date getDateFromStringWithoutExploding(String dateString) {
    try {
        return Util.getDateFromStringWithoutExploding(dateString);
    catch(ParseException e) {
        throw new IllegalArgumentException(e);
    }
}

This is reasonable, and actually reflects what's going on anyway - you know the date string you are passing in is OK, so the try-catch is perfunctory.




回答4:


It's been stated in a comment, but to make it more explicit:

public static final MY_DATE = new GregorianCalendar(2000, 1, 1).getTime();

Do this only if you can live with a mutable date assigned to a public static final.



来源:https://stackoverflow.com/questions/8471063/static-final-date-field-in-a-java-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!