How can I create a static final java.net.URL?

10,651

Solution 1

An "alternative" which I'd prefer to @HosamAly method:

private static final java.net.URL STATIC_URL = makeUrl("http://www.example.com");

public static java.net.URL makeUrl(String urlString) {
    try {
        return new java.net.URL(urlString);
    } catch (java.net.MalformedURLException e) {
        return null; //Or rethrow an unchecked exception
    }
}

Solution 2

Use a static initializer:

public class Main {
    private static final java.net.URL STATIC_URL;
    static {
        java.net.URL temp;
        try {
            temp = new java.net.URL("http://www.example.com");
        } catch (java.net.MalformedURLException e) {
            temp = null;
        }
        STATIC_URL = temp;
    }
}

Note: The usage of a temporary variable is required to avoid a compilation error about assigning to the final static field twice. If the field is not final, the assignment could be done directly.

Solution 3

If you're sure you want to hardwire a URL. Are you sure? java.net.URL is one of the most comprehensively broken classes in the JDK. In regards to use as a "constant", there is DNS lookup involved and it uses a mutable static (albeit one guarded by a security check, if you have a SecurityManager installed).

If it's just one, a static initialiser should be fine.

private static final java.net.URL STATIC_URL;

static {
    try {
        STATIC_URL = new java.net.URL("http://example.com/");
    } catch (java.net.MalformedException exc) {
        throw new Error(exc);
    }
}

(Note, you can't qualify the static field name with the class name.)

Note: You really do not want a null - throw an error of some sort and stop the class loading. I've made the constant private as it really isn't the sort of thing you want dependencies on.

If you have lots, then a method for the common code and assignment at the site of the definition is appropriate.

private static final java.net.URL STATIC_URL = constantURL("http://example.com/");

private static URL constantURL(String str) {
    try {
        return new java.net.URL("http://example.com/");
    } catch (java.net.MalformedException exc) {
        throw new Error(exc);
    }
}

Again, no nulls!

Share:
10,651
Ky -
Author by

Ky -

Any pronouns. Really, as long as you're respectful, use any singular third-person pronouns to refer to me. More about me on my site! https://KyLeggiero.me Starting on 2016-11-21 and going forward in perpetuity, all content I post on a website in the StackExchange network is written specially for that post, and is licensed under BH-0-PD unless otherwise stated.

Updated on June 29, 2022

Comments

  • Ky -
    Ky - almost 2 years

    My question is simple. I'm trying to make a set of java.net.URLs that are public static final, so that any class can access them from any context, as these URLs won't change during runtime. However, when I try to create them, I get a compiler error telling me that I must catch or declare thrown a java.net.MalformedURLException, but that is impossible outside a method. Is there any way to circumvent such a constructor that throws a non-java.lang Throwable?

    Some dummy code below to visualize my problem:

    public class Main
    {
        public static final java.net.URL STATIC_URL = new java.net.URL("http://example.com/");
        public static void main(String[] args)
        {
            GUI gui = new GUI();
            gui.setVisible(true);
        }
    }
    
    public class GUI extends java.awt.Window
    {
        public GUI()
        {
            add(new java.awt.Label(Main.STATIC_URL.toString()));
        }
    }
    

    If you try to compile this, it will tell you that you can't because of line 3. Hence my question.

  • Buhake Sindi
    Buhake Sindi over 12 years
    Compiler will complain as STATIC_URL hasn't been initialized (since you use final).
  • Buhake Sindi
    Buhake Sindi over 12 years
    Compiler error: variable STATIC_URL might not have been initialized.
  • Thomas
    Thomas over 12 years
    That is not only preferable but also circumvents the compiler error due to the final variable possibly being assigned twice.
  • Hosam Aly
    Hosam Aly over 12 years
    The final keyword could still be used. Please see my updated answer.
  • Hosam Aly
    Hosam Aly over 12 years
    Max: I agree with you, that is the preferred way of doing it. @Thomas: I've fixed the error; sorry I didn't have an IDE at hand.
  • Buhake Sindi
    Buhake Sindi over 12 years
    @Hosam Aly, no it won't. This solution (posted above) is the only solution that compiles. Yours doesn't. I've compiled it using IDE, as well as on command line, and yours failed.
  • Ky -
    Ky - over 12 years
    but is it as efficient, in terms of memory and processing time?
  • Buhake Sindi
    Buhake Sindi over 12 years
    @Supuhstar, I'm not "high-and-mighty". I just posted a code that I tested instead of rushing to post answers just for point. Besides, SO was designed to give solutions/answers that works, and not for greed. :-)
  • Ky -
    Ky - over 12 years
    sorry, I just assumed that you were being pretentious when you said something to the effect of "my solution is the only one that works, so yours can't be right"
  • Hosam Aly
    Hosam Aly over 12 years
    @TheEliteGentleman Mine compiles with javac 1.6.0_26. Which compiler version are you using?
  • Buhake Sindi
    Buhake Sindi over 12 years
    @Hosam Aly, I have the same, 64 bit version. You've edited your code, and it's effectively, exactly as mine (except, I don't use temp variable). :-)
  • bezmax
    bezmax over 12 years
    @Supuhstar Static fields are filled in only once. Also I have a feeling that this method would be inlined by compiler (not sure because of that nasty "final"). Anyway, yes, it is efficient in both memory and processing time.
  • Thomas
    Thomas over 12 years
    @Supuhstar I'd not worry about efficiency here. Normally there are many other much more inefficient parts of ones code and often you don't actually care because what is more important in most cases is developer productivity.
  • Ky -
    Ky - over 12 years
    @Thomas I am insulted. I take pride in constantly going over my code to ensure it is as efficient as possible. also, this has to be efficient because there may be hundreds of this object created at once.
  • Thomas
    Thomas over 12 years
    @Supuhstar I didn't intend to insult you :). What I basically meant is that in favor of developer productivity you don't try to optimize every tiny bit of your code. Often there will be other performance bottlenecks which often only become obvious after thorough profiling. However, many of those are not worth the trouble because you have to invest way too much in order to squeeze out a little more performance. If productivity wouldn't matter, we'd still code our software in C or even Assembler :)
  • Ky -
    Ky - over 12 years
    @Thomas I understand where you're coming from, but I am still worried about poor performance. I want my programs to be as quick-starting and responsive as Chrome.
  • bezmax
    bezmax over 12 years
    @Supuhstar Well, the problem is, if you try optimizing each place in your code as much as this URL initialization stuff, you'll use up... lets say 8 extra hours. During that time you could have had coded several extra features in your app at a cost of 50msec start-up time because of skipped micro-optimizations. Is it really worth it?
  • Ky -
    Ky - over 12 years
    @Thomas it is very much worth it. A program is made for the end user, and it is the end user for whom I work. If there is any part of my program that the end user might not like, I must abolish it, and that includes a somewhat slow startup time. If Valve pushed out their games on time instead of held them back to polish them, they might be infamous for their bugs. Because of this, they hold their games back until they feel they have a product of which they are proud. I will not release a product of which I cannot be proud.
  • Cameron Skinner
    Cameron Skinner over 12 years
    +1 for the no nulls. It really doesn't make sense to continue if one of your constants has blown up.
  • Thomas
    Thomas over 12 years
    @Supuhstar The question is: would the user recognize the extrac 50ms you squeezed out and if so would they appreciate it?
  • Thomas
    Thomas over 12 years
    As for the Valve example: games developers have to meet strict deadlines and they often work hard to get rid of as many bugs as possible. Often their initial pre-alpha releases have quite poor performance since they want to get something testable as quickly as possible. Then they optimize for their target platforms until they reach their performance goals (say 30fps/34 ms per frame). Once they reach that goal they won't invest much more effort in order to be a few ms faster, since they reached their goals. They don't optimize areas where optimizations most likely have no benefit.
  • Ky -
    Ky - over 12 years
    I believe they will, especially since individual class loading times add up fast. As for your counter to the Valve example, they indeed do optimize the performance. Try playing Portal 2 on an older computer, which just meets the system requirements, and then try playing Portal. Portal 2 will almost always run better because Valve invested more time and effort into improving the source engine. Their games are "late" because they care about the end product. My programs have no release time, and I believe no one's should. Any well-made program should be released only after the creator is proud.
  • bezmax
    bezmax over 12 years
    @Supuhstar So what you are saying is that Portal 1 was not optimized to the edge and that it had to be released with performance issues, right? And you are using that to prove that Valve only release perfect products? Am I missing something in your statements?
  • Ky -
    Ky - over 12 years
    You're missing the pride. My philosophy is one of pride. If I can't be proud of a product, I can't release it. Now, please tell me this is the key to that oh-so-private information you've been withholding. Which method of static initialization is faster?
  • bezmax
    bezmax over 12 years
    Technically, the "fastest" way for static initialization would be what @HosamAly proposed. However, to make it faster than my solution - you would need to bundle as many as possible URL initializations inside of one try-catch block. The reason for that is that try-catch operation is somewhat resource-heavy. So if you use try-catch for each variable, it will be somewhat slower than if you bundle them all into one try-catch block. However, personally I prefer a clear and understandable code. You will see what I mean after you actually try initializing several URLs in one try-catch block.
  • Flame
    Flame almost 12 years
    I'd like to see a suggestion to use java.net.URI instead also. If using a library that requires a URL, use the toURL() method at that point.
  • Ky -
    Ky - over 7 years
    In the 5 years since posting this question and accepting an answer, I've decided to make this the accepted answer since it's a lot easier to understand, and much more functional.
  • bezmax
    bezmax over 7 years
    @Supuhstar What about the pride? ;)
  • Ky -
    Ky - over 7 years
    @bezmax haha it's still there! Just also now balancing pride of speed with pride of exemplary code. Working with teams changed me :P