Приведение строки к общему типу c - PullRequest
1 голос
/ 18 июня 2020

Я пишу клиент GUI для управления и отображения двоичных деревьев. Сложность здесь в том, что деревья относятся к общему типу c. Я нахожусь в ситуации, когда мне нужно передать своему серверу значение, полученное от пользователя с помощью Message<T>, который является сериализуемым объектом, хранящим запрос и его значение для сервера. Моя проблема в том, что значение типа T получается с использованием JOptionPane.showInputDialog, которое возвращает String.

Есть ли способ получить ввод от пользователя в виде типа T или преобразовать String в указанный тип?

Основной класс:

import javax.swing.JOptionPane;

public class Main {

  public static void main(String[] args) {

    Object[] options = {"Integer", "Double", "String"};
    int result = JOptionPane
        .showOptionDialog(null, "Please, select the type of the tree:", "Selection of the type",
            JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);

    switch (result) {
      case 0:
        MyFrame<Integer> frameInteger = new MyFrame<>("Integer");
        frameInteger.setVisible(true);
        break;
      case 1:
        MyFrame<Double> frameDouble = new MyFrame<>("Double");
        frameDouble.setVisible(true);
        break;
      case 2:
        MyFrame<String> frameString = new MyFrame<>("String");
        frameString.setVisible(true);
      default:
        throw new IllegalArgumentException("Invalid type.");
    }
  }

}

JFrame / Класс клиента:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class MyFrame<T extends Comparable<T>> extends JFrame {

  Socket client;
  JPanel context = new JPanel();
  String address;
  ObjectInputStream in;
  ObjectOutputStream out;
  BinaryTree<T> tree;
  boolean result;
  String type;

  public MyFrame(String type) {
    this.type = type;
    address = JOptionPane.showInputDialog("Please enter the address and port (e.g. 127.0.0.1:5555)");
    try {
      client = new Socket(address.split(":")[0], Integer.parseInt(address.split(":")[1]));
      in = new ObjectInputStream(client.getInputStream());
      out = new ObjectOutputStream(client.getOutputStream());
    } catch (Exception e) {
      System.err.println("It wasn't possible to obtain the address from the given input.");
    }

    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(1024, 720);
    setLocationRelativeTo(null);
    setTitle("Binary Tree Client");

    initUI();
  }

  private void initUI() {
    JMenuBar menuBar = new JMenuBar();
    JMenu file = new JMenu("File...");
    JMenu edit = new JMenu("Edit");

    JMenuItem close = new JMenuItem("Close");

    JMenuItem insert = new JMenuItem("Insert...");
    JMenuItem delete = new JMenuItem("Delete...");
    JMenuItem search = new JMenuItem("Search...");

    close.addActionListener(e -> System.exit(0));

    insert.addActionListener(e -> {
      String value = JOptionPane.showInputDialog("Please insert the node value:");

      // here is the problem
      tree = exchange(new ClientMessage<T>("INSERT", value)).getTree();

    });

    file.add(close);

    edit.add(insert);
    edit.add(delete);
    edit.add(search);

    menuBar.add(file);
    menuBar.add(edit);

    setJMenuBar(menuBar);
  }

  public ServerMessage<T> exchange(ClientMessage<T> clientMsg) {
    try {
      out.writeObject(clientMsg);
      return (ServerMessage<T>) in.readObject();
    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
      return null;
    }
  }
}

Класс ClientMessage:

import java.io.Serializable;

public class ClientMessage<T extends Comparable<T>> implements Serializable {

  private String request;
  private T value;

  public ClientMessage(String request, T value) {
    this.request = request;
    this.value = value;
  }

  public String getRequest() {
    return request;
  }

  public T getValue() {
    return value;
  }
}

И ServerThread Class , где я хочу использовать значение:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class ServerThread<T extends Comparable<T>> extends Thread {

  BinaryTree<T> tree;
  ObjectInputStream in;
  ObjectOutputStream out;
  Socket client;

  public ServerThread(Socket client) {
    this.client = client;
  }

  @Override
  @SuppressWarnings("unchecked")
  public void run() {
    try {
      in = new ObjectInputStream(client.getInputStream());
      out = new ObjectOutputStream(client.getOutputStream());

      ClientMessage<T> request;
      ServerMessage<T> response = new ServerMessage<>();

      while ((request = (ClientMessage<T>) in.readObject()) != null) {
        handleRequest(request, response);

        response.setTree(tree);
        out.writeObject(response);
      }

    } catch (IOException | ClassNotFoundException e) {
      e.printStackTrace();
    }
  }

  private void handleRequest(ClientMessage<T> request, ServerMessage<T> response) {

    switch (request.getRequest()) {
      case "SET":
        tree = new BinaryTree<>();
        break;
      case "INSERT":
        tree.insert(request.getValue());
        break;
      case "DELETE":
        tree.delete(request.getValue());
        break;
      case "SEARCH":
        response.setResult(tree.search(request.getValue()));
        break;
      default:
        throw new IllegalArgumentException("Invalid request.");
    }
  }
}

1 Ответ

1 голос
/ 18 июня 2020

Измените свой MyFrame класс, чтобы он принимал Class<T>:

Class<T> type;

public MyFrame(Class<T> type) {
  this.type = type;
  ...
}

и назовите его, например:

MyFrame<Integer> frameInteger = new MyFrame<>(Integer.class);

Или, поскольку вы явно не используете type поле, просто удалите поле type и параметр конструктора и вызовите как:

MyFrame<Integer> frameInteger = new MyFrame<>();
...