Является ли приемлемой практикой в ​​Java вложение операторов try / catch? - PullRequest
4 голосов
/ 25 апреля 2011

Я пытаюсь создать IP-адрес в Android из переданного значения (с помощью Bundle), и, если это не удается, я создаю его с использованием стандартного IP-адреса, который жестко закодирован. Если это не помогло, я закрываю приложение.

Что я хотел бы знать, так это то, что можно вложить «попробуй / поймать», как я это сделал здесь, или есть лучший способ.

try {
    // serverSettings is the Bundle name that was passed in.
    ipAddress = InetAddress.getByName(serverSettings.getString("serverIp"));
} catch (UnknownHostException e) {
    Log.e("ERROR:", "IOException: Failed to create IP, trying default");
    try {
        // DEFAULT_IP is the hard-coded default fall-back address
        ipAddress = InetAddress.getByName(DEFAULT_IP);
    } catch (UnknownHostException e1) {
        Log.e("ERROR:", "IOException: Total fail, exiting");
        e1.printStackTrace();
        finish();
    }
}

Ответы [ 6 ]

9 голосов
/ 25 апреля 2011

Это законная Java. Это выглядит неуклюже для меня, и я, вероятно, сделал бы это по-другому, но это верно и работает.

Вот как бы я это сделал:

public InetAddress getServerAddress() {
    for (String address : new String[] {serverSettings.getString("serverIp"), DEFAULT_IP}) {
        try {
            return InetAddress.getByName(address);
        } catch (UnknownHostException e) {
            Log.e("ERROR:", "Cannot resolve " + address);
        }
    }
    Log.e("ERROR:", "Total fail, exiting");
    finish();
    return null;    // not reached
}
4 голосов
/ 25 апреля 2011

Я думаю, будет спорным, какой способ лучше, но вот еще один вариант, который некоторые могут посчитать немного более «выразительным» и читабельным, хотя это больше строк кода:

public InetAddress tryHost(String hostName) {
    InetAddress address = null;
    try {
        address = InetAddress.getByName(hostName);
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    return null;
}

Тогда в вашем коде просто выполните:

InetAddress address = null;
address = tryHost(serverSettings.getString("serverIp"));
if (address = null)
    address = tryHost(DEFAULT_IP);
if (address = null) {
    // handle error, throw exception
}
finish();
2 голосов
/ 25 апреля 2011

Другой вариант - сначала установить значение по умолчанию:

ipAddress = null;
try {
    // serverSettings is the Bundle name that was passed in.
    ipAddress = InetAddress.getByName(DEFAULT_IP); // Set default address
    ipAddress = InetAddress.getByName(serverSettings.getString("serverIp")); // Try passed-in address
} catch (UnknownHostException e) {
    if (ipAddress == null) {
        Log.e("ERROR:", "IOException: Total fail, exiting");
        e1.printStackTrace();
        finish();
    }
}

Если вызов, использующий значение Bundle'd, завершится неудачно, то перед изменением ipAddress выдается исключение, поэтому ipAddress уже установлен по умолчанию. Конечно, это допустимый шаблон, только если DEFAULT_IP всегда должен быть разрешаем.

1 голос
/ 25 апреля 2011

Я предпочитаю это. Это немного чище и не требует дополнительных флагов.

InetAddress ipAddress = null;
try {
    // serverSettings is the Bundle name that was passed in.
    ipAddress = InetAddress.getByName(serverSettings.getString("serverIp"));
} catch (UnknownHostException e) {
    Log.e("ERROR:", "IOException: Failed to create IP, trying default");
}
if(ipAddress==null){
    try {
        // DEFAULT_IP is the hard-coded default fall-back address
        ipAddress = InetAddress.getByName(DEFAULT_IP);

    } catch (UnknownHostException e1) {
        Log.e("ERROR:", "IOException: Total fail, exiting");
        e1.printStackTrace();
        finish();
    }
}
1 голос
/ 25 апреля 2011

Все нормально. Вы также можете использовать логический флаг, который включается в первом улове, поэтому вы выполняете запрос по IP вне улова, если ваш логический флаг включен.

boolean failed = false;
try {
    // serverSettings is the Bundle name that was passed in.
    ipAddress = InetAddress.getByName(serverSettings.getString("serverIp"));
} catch (UnknownHostException e) {
    failed = true;
    Log.e("ERROR:", "IOException: Failed to create IP, trying default");    
}

if(failed){
    try {
            // DEFAULT_IP is the hard-coded default fall-back address
            ipAddress = InetAddress.getByName(DEFAULT_IP);
        } catch (UnknownHostException e1) {
            Log.e("ERROR:", "IOException: Total fail, exiting");
            e1.printStackTrace();
            finish();
        }
    }
}
0 голосов
/ 27 апреля 2011

Еще один вариант, который мне нравится при работе с большим набором тестов (на основе первых выигрышей):

ipAddress = null;
// serverSettings is the Bundle name that was passed in.
String[] addresses = { DEFAULT_IP,
                       serverSettings.getString("serverIp") };

int i = 0;
do {
    try {
        ipAddress = InetAddress.getByName(addresses[i]);
    } catch (UnknownHostException e) {
        Log.e("ERROR:", "IOException: Failed to create IP, trying next");
    }
} while (ipAddress == null && i < addresses.length);

if (ipAddress == null) {
    Log.e("ERROR:", "IOException: Total fail, exiting");
    e1.printStackTrace();
    finish();
}

Это, вероятно, более уместно в моем обычном случае использования (циклически перебирая SimpleDateFormats для соответствияСторонние строки даты)

...