简体   繁体   中英

Casting a String to a generic type <T extends Comparable<T>>

I'm writing a GUI client for manipulating and displaying binary trees. The tricky part here is that the trees are of a generic type. I'm in the situation where I have to pass my server a value obtained from a user with the help of Message<T> , which is a Serializable object, storing a request and its value for the server. My problem is that the value of the type T is obtained using JOptionPane.showInputDialog , which returns String .

Is there any way to get the input from the user in the form of the T type or to convert the String to mentioned type?

Main Class:

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/Client Class:

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 Class:

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;
  }
}

And the ServerThread Class where I want to use the value:

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.");
    }
  }
}

Change your MyFrame class to accept a Class<T> :

Class<T> type;

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

and call like:

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

Or, since you don't apparently use the type field, just remove the type field and the constructor parameter, and call like:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM