#java #переменные #инициализация #try_catch
Проблема заключается в необходимости задания значения final переменной (connectionSocket2)
в try-блоке. В дальнейшей части кода (в части run()) этого не видно и возникает как
бы ошибка, что та переменная не определена:
final Socket connectionSocket;
try { connectionSocket = welcomeSocket.accept(); }
The local variable connectionSocket2 may not have been initialized
убрать final не могу, так как (в части run()) дает ошибку
Cannot refer to the non-final local variable connectionSocket defined
in an enclosing scope
Socket connectionSocket2=null;
try { connectionSocket2 = welcomeSocket.accept();
} catch (IOException e2) { e2.printStackTrace(); }
final Socket connectionSocket=connectionSocket2; try{connectionSocket2.close();}catch(IOException
e1){e1.printStackTrace();}
service.submit(new Runnable() {
public void run() {
while (true) {
BufferedReader inFromClient=null;
DataOutputStream outToClient=null;
try{
inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes(inFromClient.readLine());
} catch(IOException ioe) {} }}});
Статической делать не могу - для каждого потока создается свое соединение, как бы
свой экземпляр этой переменной.
Приведенный код работает, использовал вторую переменную для передачи ей значения
и дальнейшего использования именной второй переменной. Но это выглядит плохо.
Как правильно, профессионально быть в этой ситуации? Модно ли как-то сказать компилятору,
что переменная на самом деле уже определена в try блоке и ему нечего "волноваться"?
(типа динамическая переменная, как в .Net)
Ответы
Ответ 1
Ответ-вопросник и очередной наброс на медальку. Итак, у вас было что-то вот такое: public class ICanIntoSockets { public static void main( String[] args ) throws IOException { ServerSocket welcomeSocket = new ServerSocket(10000); ExecutorService service = Executors.newCachedThreadPool(); doWork( welcomeSocket, service ); } public static void doWork( ServerSocket welcomeSocket, ExecutorService service ) { try { while (true) { final Socket connectionSocket = welcomeSocket.accept(); service.execute( () -> { try ( Socket socket = connectionSocket; BufferedReader inFromClient = new BufferedReader( new InputStreamReader(socket.getInputStream())); DataOutputStream outToClient = new DataOutputStream( socket.getOutputStream())) { outToClient.writeBytes(inFromClient.readLine()); } catch (IOException ioe) { ioe.printStackTrace(); } }); } } catch ( IOException ex ) { ex.printStackTrace(); } } } но try - плохо, и торморзит на тысячах подключений (тесты где?), поэтому вы решили от него избавиться. Ява - убогий язык, в ней зачем-то придумали Checked Exceptions и напихали во все места в стандартной библиотеке, поэтому совсем без try - никак: public static void doWork( ServerSocket welcomeSocket, ExecutorService service ) { while (true) { final Socket connectionSocket; try { connectionSocket = welcomeSocket.accept(); } catch (IOException ex) { ex.printStackTrace(); } service.execute(() -> { try ( Socket socket = connectionSocket; // The local variable connectionSocket may not have been initialized BufferedReader inFromClient = new BufferedReader( new InputStreamReader(socket.getInputStream())); DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream())) { outToClient.writeBytes(inFromClient.readLine()); } catch (IOException ioe) { ioe.printStackTrace(); } }); } } Зло загнано в угол в одной строчке кода! Но компилятор почему-то считает, что переменная connectionSocket может быть не инициализирована. Почему? Потому что есть путь выполнения программы, при которой она действительно не инициализируется: когда welcomeSocket.accept() выбрасывает исключение. Метод не возвращает значение - значение переменной не присваивается. Что же делать? Не надо продолжать выполнение итерации, ваш код все равно не сможет работать дальше без клиентского сокета. Сделайте внутри catch-блока return, break, continue (в надежде, что следующий accept не выбросит исключение, что вряд ли). Если код непременно должен продолжаться дальше - присвойте connectionSocket null и где-то сделайте проверку. Предложенный вариант с массивом - это либо то самое создание объектов и выделение памяти, с которым вы сражаетесь, либо потеря подключений и обработка одного подключения несколько раз, смотря где вы этот массив объявите.Ответ 2
Можно обёртку сделать: public class MySocket{ private Socket mSocket; public MySocket(){ } public void setSocket(Socket socket){ mSocket = socket; } public Socket getSocket(){ return mSocket; } } И создать его экземпляр: final MySocket connectionSocket = new MySocket(); И дальше: try{ connectionSocket.setSocket(welcomeSocket.accept()); } catch (IOException e2) { e2.printStackTrace(); } И внутри Runnable обращаться к connectionSocket.getSocket().Ответ 3
создайте final Socket[] на один элемент и в пишите в него.
Комментариев нет:
Отправить комментарий