comments inline...

On 01/08/2013 22:18, Stuart Marks wrote:
On 7/31/13 2:39 PM, Matthew Hall wrote:
On Wed, Jul 31, 2013 at 02:38:26PM -0700, Stuart Marks wrote:
The alternative is to add "@throws SocketException never" to the
javadoc, just to get rid of the doclint warning, but this has the
consequence of requiring people to keep dead code around
indefinitely, and furthermore it requires them to add new dead code
every time they create a DatagramPacket.

I have never understood in many years using Java why the compiler
generates
errors about attempting to catch supposedly-impossible exceptions,
instead of
warnings.

For me it only leads to difficulties when I'm trying to write
prototypes or
refactor and clean up some old brittle code, and I run into that rather
dubious sort of error.

This is a good example of where it causes more harm than good. Is
there still
a really good reason for this over-paranoid compiler error given that
checked
exceptions aren't as popular as they used to be anyways?

I don't have the definitive answer, but it was a very early Java design
decision to make unreachable code be a compilation error instead of a
warning. This is a matter of judgment, of course; reasonable people come
down on different sides of this, for different cases. For example, see
this Stackoverflow conversation:

http://stackoverflow.com/questions/3795585/why-does-java-have-an-unreachable-statement-compiler-error


* * *

Meanwhile, I did a little bit of studying about DatagramPacket. The
doclint warnings occur on two of the six DatagramPacket constructors:

DatagramPacket(byte[] buf, int len, SocketAddress sa)
DatagramPacket(byte[] buf, int off, int len, SocketAddress sa)

There are two other equivalent overloaded constructors that take
InetAddress and port arguments:

DatagramPacket(byte[] buf, int len, InetAddress ia, int port)
DatagramPacket(byte[] buf, int off, int len, InetAddress ia, int port)

To my eye the InetAddress/port constructors are used quite a bit more
often than the SocketAddress ones. I did a web search for "java
DatagramPacket example" and looked at all the examples on the first page
of hits. All of them used the InetAddress+port constructor overloads
(including the Oracle Java tutorial). I didn't see any uses of the
SocketAddress overloads.

I also did an ohloh search for "new DatagramPacket(":

http://code.ohloh.net/search?s=%22new%20DatagramPacket%28%22&p=2&pp=0&fl=Java&mp=1&ml=1&me=1&md=1&ff=1&filterChecked=true

Thank you Stuart, this is really helpful.

(HT: Dalibor)

I looked through around 100 examples, and the vast majority of them use
the InetAddress+port overloads. I saw three examples that use the

I would tend to agree with this, the InetAddress+port are probably most commonly used. The SocketAddress variants are useful when you have already constructed an InetSocketAddress elsewhere and pass it into the method that creates/sends the packet. I can only find this sort of code in tests.

Also worth noting is that typically datagram packets are created in close proximity to the code that sends them, and the sending of a packet requires handling IOE. This, IMO, further reduces the impact of removing 'throw SE'.

SocketAddress overloads. Two of them were within methods that declared
"throws Exception." The third was within a try/catch block that catches
IOException. None of the three cases would suffer a source incompatibility.

I cannot comment on the code you are talking about, but removing 'throws SE' from these constructors will affect anyone that is catching IOE ( since SE is a subclass of IOE ). Simple test:

: cat ThrowingCtrs.java
import java.net.*;
import java.io.IOException;

public class ThrowingCtrs {

    public static void main(String[] args) {
        SocketAddress sa = new InetSocketAddress("127.0.0.1", 45678);

        // DatagramPacket(byte[], int, SocketAddress)
        try { DatagramPacket dp = new DatagramPacket(new byte[1], 1, sa); }
        catch (SocketException x) { }

        try { DatagramPacket dp = new DatagramPacket(new byte[1], 1, sa); }
        catch (IOException x) { }

        try { DatagramPacket dp = new DatagramPacket(new byte[1], 1, sa); }
        catch (Exception x) { }

        // DatagramPacket(byte[], int, int, SocketAddress)
try { DatagramPacket dp = new DatagramPacket(new byte[1], 0, 1, sa); }
        catch (SocketException x) { }

try { DatagramPacket dp = new DatagramPacket(new byte[1], 0, 1, sa); }
        catch (IOException x) { }

try { DatagramPacket dp = new DatagramPacket(new byte[1], 0, 1, sa); }
        catch (Exception x) { }
    }
}

Output of javac from a build with SE removed.
 build/solaris-x86_64-normal-server-release/jdk/bin/javac ThrowingCtrs.java
ThrowingCtrs.java:11: error: exception SocketException is never thrown in body of corresponding try statement
        catch (SocketException x) { }
        ^
ThrowingCtrs.java:14: error: exception IOException is never thrown in body of corresponding try statement
        catch (IOException x) { }
        ^
ThrowingCtrs.java:21: error: exception SocketException is never thrown in body of corresponding try statement
        catch (SocketException x) { }
        ^
ThrowingCtrs.java:24: error: exception IOException is never thrown in body of corresponding try statement
        catch (IOException x) { }
        ^
4 errors

This isn't definitive, of course, but it does seem to supply some
evidence that making this change would result in a relatively minor
source incompatibility.

Given the above, I still agree with the sentiment here. I will file a bug and proceed with the necessary changes to remove SE.

Thanks again,
-Chris.


s'marks

Reply via email to