0

問題について助けが必要です。テキスト ファイルから 2000 個のプロキシのリストを読み込もうとしていますが、クラスは 1040 個の配列インデックスしか各行で読み取ったもので埋めません。

どうすればいいのかわからない。:(

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ProxyLoader {

private String[] lineSplit = new String[100000];
private static String[] addresses = new String[100000];
private static int[] ports = new int[100000];
public int i = 0;

public ProxyLoader() {
    readData();
}

public synchronized String getAddr(int i) {
    return this.addresses[i];
}

public synchronized int getPort(int i) {
    return this.ports[i];
}

public synchronized void readData() {
    try {
        BufferedReader br = new BufferedReader(
                new FileReader("./proxy.txt"));
        String line = "";

        try {
            while ((line = br.readLine()) != null) {

                lineSplit = line.split(":");
                i++;

                addresses[i] = lineSplit[0];
                ports[i] = Integer.parseInt(lineSplit[1]);
                System.out.println("Line Number [" + i + "]  Adr: "
                        + addresses[i] + " Port: " + ports[i]);
            }

            for (String s : addresses) {
                if (s == null) {
                    s = "127.0.0.1";
                }
            }

            for (int x : ports) {
                if (x == 0) {
                    x = 8080;
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
}

}
4

2 に答える 2

1

ユース ケースに正確に適合しない可能性があるいくつかの例を含めましたが、保守と読み取りが少し簡単なコードを作成する方法をいくつか示します。

読みにくく、デバッグや保守が難しいコード。

  • オブジェクトは入力 (コンストラクター引数) を検証する必要があります。
  • 不良データを拒否します。後でデバッグするのが難しくなったときに、早く失敗してください。
  • 回復できない限り、例外をキャッチしないでください。それを柔らかくする (ランタイムにラップして再スローする) か、throws 句に追加します。どうすればいいのかわからない場合は、何もしないでください。
  • 例外を食べることはありません。投げ直すか、処理してください。
  • あなたのコードは、それが必要ないことを述べ続けています。
  • クラスは、gak の 2 つの配列よりも自己記述的です。
  • public var は避けてください。それらが最終的なものでない限り。
  • オブジェクトの状態を保護します。
  • メソッドがどのように呼び出されるかを考え、副作用を避けてください。readData を 2 回呼び出すと、デバッグが困難な奇妙な副作用が発生する
  • メモリは安価ですが無料ではありません。必要のない大きな配列をインスタンス化しないでください。
  • 開いたら、閉じなければなりません。

Java 7 および 8 では、FileSystem から行を読み取ることができるため、最初からこのコードのほとんどを記述する必要はありません。

 Path thePath = FileSystems.getDefault().getPath(location);
 return Files.readAllLines(thePath, Charset.forName("UTF-8"));

多数の小さなファイルを行に読み込む必要があり、FileSystem を使用したくない場合、または Java 6 または Java 5 を使用している場合は、次のようにユーティリティ クラスを作成します。

public class IOUtils {

    public final static String CHARSET = "UTF-8";

...

public static List<String> readLines(File file) {
    try (FileReader reader = new FileReader(file)) {
        return readLines(reader);
    } catch (Exception ex) {
        return Exceptions.handle(List.class, ex);
    }
}

これは Reader を取る readLines を呼び出します:

public static List<String> readLines(Reader reader) {

    try (BufferedReader bufferedReader = new BufferedReader(reader)) {
          return readLines(bufferedReader);
    } catch (Exception ex) {
        return Exceptions.handle(List.class, ex);
    }
}

BufferedReader を取る readLines を呼び出します。

public static List<String> readLines(BufferedReader reader) {
    List<String> lines = new ArrayList<>(80);

    try (BufferedReader bufferedReader = reader) {


        String line = null;
        while ( (line = bufferedReader.readLine()) != null) {
        lines.add(line);
        }

    } catch (Exception ex) {

        return Exceptions.handle(List.class, ex);
    }
    return lines;
}

Apache には、Apache コモンズ ( http://commons.apache.org/ )と呼ばれる一連のユーティリティがあります。これには lang が含まれ、IO ユーティリティ ( http://commons.apache.org/proper/commons-io/ ) が含まれます。Java 5 または Java 6 を使用している場合は、これらのいずれかがあればよいでしょう。

例に戻ると、任意の場所を行のリストに変えることができます。

public static List<String> readLines(String location) {
    URI uri =  URI.create(location);

    try {

        if ( uri.getScheme()==null ) {

            Path thePath = FileSystems.getDefault().getPath(location);
            return Files.readAllLines(thePath, Charset.forName("UTF-8"));

        } else if ( uri.getScheme().equals("file") ) {

            Path thePath = FileSystems.getDefault().getPath(uri.getPath());
            return Files.readAllLines(thePath, Charset.forName("UTF-8"));

        } else {
            return readLines(location, uri);
        }

    } catch (Exception ex) {
         return Exceptions.handle(List.class, ex);
    }

}

FileSystem、Path、URI などはすべて JDK にあります。

例を続ける:

private static List<String> readLines(String location, URI uri) throws Exception {
    try {

        FileSystem fileSystem = FileSystems.getFileSystem(uri);
        Path fsPath = fileSystem.getPath(location);
        return Files.readAllLines(fsPath, Charset.forName("UTF-8"));

    } catch (ProviderNotFoundException ex) {
         return readLines(uri.toURL().openStream());
    }
}

上記は FileSystem から uri を読み取ろうとし、読み込めない場合は URL ストリーム経由で検索します。URL、URI、ファイル、ファイルシステムなどはすべて JDK の一部です。

URL ストリームを Reader に変換し、次に使用する文字列に変換するには、次のようにします。

public static List<String> readLines(InputStream is) {

    try (Reader reader = new InputStreamReader(is, CHARSET)) {

        return readLines(reader);

    } catch (Exception ex) {

        return Exceptions.handle(List.class, ex);
    }
}

:)

それでは、例に戻りましょう (ファイルを含むどこからでも行を読み取ることができるようになりました)。

public static final class Proxy {
    private final String address;
    private final int port;
    private static final String DATA_FILE = "./files/proxy.txt";

    private static final Pattern addressPattern = Pattern.compile("^(\\d{1,3}[.]{1}){3}[0-9]{1,3}$");

    private Proxy(String address, int port) {

        /* Validate address in not null.*/
        Objects.requireNonNull(address, "address should not be null");

        /* Validate port is in range. */
        if (port < 1 || port > 65535) {
            throw new IllegalArgumentException("Port is not in range port=" + port);
        }

        /* Validate address is of the form 123.12.1.5 .*/
        if (!addressPattern.matcher(address).matches()) {
            throw new IllegalArgumentException("Invalid Inet address");
        }

        /* Now initialize our address and port. */
        this.address = address;
        this.port = port;
    }

    private static Proxy createProxy(String line) {
        String[] lineSplit = line.split(":");
        String address = lineSplit[0];
        int port =  parseInt(lineSplit[1]);
        return new Proxy(address, port);
    }

    public final String getAddress() {
        return address;
    }

    public final int getPort() {
        return port;
    }

    public static List<Proxy> loadProxies() {
        List <String> lines = IOUtils.readLines(DATA_FILE);
        List<Proxy> proxyList  = new ArrayList<>(lines.size());

        for (String line : lines) {
            proxyList.add(createProxy(line));
        }
        return proxyList;
    }

}

不変の状態がないことに注意してください。これにより、バグが防止されます。また、コードのデバッグとサポートが容易になります。

ファイル システムから行を読み取る IOUtils.readLines に注目してください。

Proxy のインスタンスが不正な状態で初期化されないようにするための、コンストラクターでの余分な作業に注意してください。これらはすべて JDK オブジェクト、パターンなどにあります。

再利用可能な ProxyLoader が必要な場合は、次のようになります。

public static class ProxyLoader {
    private static final String DATA_FILE = "./files/proxy.txt";


    private List<Proxy> proxyList = Collections.EMPTY_LIST;
    private final String dataFile;

    public ProxyLoader() {
        this.dataFile = DATA_FILE;
        init();
    }

    public ProxyLoader(String dataFile) {
        this.dataFile = DATA_FILE;
        init();
    }

    private void init() {
        List <String> lines = IO.readLines(dataFile);
        proxyList = new ArrayList<>(lines.size());

        for (String line : lines) {
            proxyList.add(Proxy.createProxy(line));
        }
    }

    public String getDataFile() {
        return this.dataFile;
    }

    public static List<Proxy> loadProxies() {
            return new ProxyLoader().getProxyList();
    }

    public List<Proxy> getProxyList() {
        return proxyList;
    }
   ...

}

public static class Proxy {
    private final String address;
    private final int port;

    ...

    public Proxy(String address, int port) {
        ... 
        this.address = address;
        this.port = port;
    }

    public static Proxy createProxy(String line) {
        String[] lineSplit = line.split(":");
        String address = lineSplit[0];
        int port =  parseInt(lineSplit[1]);
        return new Proxy(address, port);
    }

    public String getAddress() {
        return address;
    }

    public int getPort() {
        return port;
    }
}

コーディングは素晴らしいです。テストは神です!この例のいくつかのテストを次に示します。

public static class ProxyLoader {
    private static final String DATA_FILE = "./files/proxy.txt";


    private List<Proxy> proxyList = Collections.EMPTY_LIST;
    private final String dataFile;

    public ProxyLoader() {
        this.dataFile = DATA_FILE;
        init();
    }

    public ProxyLoader(String dataFile) {
        this.dataFile = DATA_FILE;
        init();
    }

    private void init() {
        List <String> lines = IO.readLines(dataFile);
        proxyList = new ArrayList<>(lines.size());

        for (String line : lines) {
            proxyList.add(Proxy.createProxy(line));
        }
    }

    public String getDataFile() {
        return this.dataFile;
    }

    public static List<Proxy> loadProxies() {
            return new ProxyLoader().getProxyList();
    }

    public List<Proxy> getProxyList() {
        return proxyList;
    }

}

public static class Proxy {
    private final String address;
    private final int port;

    public Proxy(String address, int port) {
        this.address = address;
        this.port = port;
    }

    public static Proxy createProxy(String line) {
        String[] lineSplit = line.split(":");
        String address = lineSplit[0];
        int port =  parseInt(lineSplit[1]);
        return new Proxy(address, port);
    }

    public String getAddress() {
        return address;
    }

    public int getPort() {
        return port;
    }
}

これは、すべて1つのクラスの代替手段です。(ProxyLoader にはあまり意味がありませんでした)。

public static final class Proxy2 {
    private final String address;
    private final int port;
    private static final String DATA_FILE = "./files/proxy.txt";

    private static final Pattern addressPattern = Pattern.compile("^(\\d{1,3}[.]{1}){3}[0-9]{1,3}$");

    private Proxy2(String address, int port) {

        /* Validate address in not null.*/
        Objects.requireNonNull(address, "address should not be null");

        /* Validate port is in range. */
        if (port < 1 || port > 65535) {
            throw new IllegalArgumentException("Port is not in range port=" + port);
        }

        /* Validate address is of the form 123.12.1.5 .*/
        if (!addressPattern.matcher(address).matches()) {
            throw new IllegalArgumentException("Invalid Inet address");
        }

        /* Now initialize our address and port. */
        this.address = address;
        this.port = port;
    }

    private static Proxy2 createProxy(String line) {
        String[] lineSplit = line.split(":");
        String address = lineSplit[0];
        int port =  parseInt(lineSplit[1]);
        return new Proxy2(address, port);
    }

    public final String getAddress() {
        return address;
    }

    public final int getPort() {
        return port;
    }

    public static List<Proxy2> loadProxies() {
        List <String> lines = IO.readLines(DATA_FILE);
        List<Proxy2> proxyList  = new ArrayList<>(lines.size());

        for (String line : lines) {
            proxyList.add(createProxy(line));
        }
        return proxyList;
    }

}

次に、テストを作成します (テストと TDD は、これらの問題を乗り越えるのに役立ちます)。

@Test public void proxyTest() {
    List<Proxy> proxyList = ProxyLoader.loadProxies();
    assertEquals(
            5, len(proxyList)
    );


    assertEquals(
            "127.0.0.1", idx(proxyList, 0).getAddress()
    );



    assertEquals(
            8080, idx(proxyList, 0).getPort()
    );


    //192.55.55.57:9091
    assertEquals(
            "192.55.55.57", idx(proxyList, -1).getAddress()
    );



    assertEquals(
            9091, idx(proxyList, -1).getPort()
    );


}

idx などは、boon という独自のヘルパー ライブラリで定義されています。idx メソッドは、Python または Ruby のスライス表記のように機能します。

@Test public void proxyTest2() {
    List<Proxy2> proxyList = Proxy2.loadProxies();
    assertEquals(
            5, len(proxyList)
    );


    assertEquals(
            "127.0.0.1", idx(proxyList, 0).getAddress()
    );



    assertEquals(
            8080, idx(proxyList, 0).getPort()
    );


    //192.55.55.57:9091
    assertEquals(
            "192.55.55.57", idx(proxyList, -1).getAddress()
    );



    assertEquals(
            9091, idx(proxyList, -1).getPort()
    );


}

私の入力ファイル

127.0.0.1:8080
192.55.55.55:9090
127.0.0.2:8080
192.55.55.56:9090
192.55.55.57:9091

そして、私のIOUtils(実際にはIOと呼ばれます)はどうですか:

これはIO(utils)を気にする人のためのテストです:

package org.boon.utils;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.*;
import java.util.regex.Pattern;

import static javax.lang.Integer.parseInt;
import static org.boon.utils.Lists.idx;
import static org.boon.utils.Lists.len;
import static org.boon.utils.Maps.copy;
import static org.boon.utils.Maps.map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

...

これにより、関連するインポートのアイデアが得られます。

public class IOTest {

....

以下は、ファイル システム上のファイルから行を読み取るテストです。

@Test
public void testReadLines() {
    File testDir = new File("src/test/resources");
    File testFile = new File(testDir, "testfile.txt");


    List<String> lines = IO.readLines(testFile);

    assertLines(lines);

}

ファイルが正しく読み取られたことをアサートするヘルパー メソッドを次に示します。

private void assertLines(List<String> lines) {

    assertEquals(
            4, len(lines)
    );


    assertEquals(
            "line 1", idx(lines, 0)
    );



    assertEquals(
            "grapes", idx(lines, 3)
    );
}

これは、文字列パスからファイルを読み取ることを示すテストです。

@Test
public void testReadLinesFromPath() {


    List<String> lines = IO.readLines("src/test/resources/testfile.txt");

    assertLines(lines);



}

このテストは、URI からのファイルの読み取りを示しています。

@Test
public void testReadLinesURI() {

    File testDir = new File("src/test/resources");
    File testFile = new File(testDir, "testfile.txt");
    URI uri = testFile.toURI();


    //"file:///....src/test/resources/testfile.txt"
    List<String> lines = IO.readLines(uri.toString());
    assertLines(lines);


}

以下は、HTTP サーバーからファイルから行を読み取ることができることを示すテストです。

static class MyHandler implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {

        File testDir = new File("src/test/resources");
        File testFile = new File(testDir, "testfile.txt");
        String body = IO.read(testFile);
        t.sendResponseHeaders(200, body.length());
        OutputStream os = t.getResponseBody();
        os.write(body.getBytes(IO.CHARSET));
        os.close();
    }
}

HTTP サーバー テスト (HTTP サーバーをインスタンス化します) を次に示します。

@Test
public void testReadFromHttp() throws Exception {

    HttpServer server = HttpServer.create(new InetSocketAddress(9666), 0);
    server.createContext("/test", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();

    Thread.sleep(1000);

    List<String> lines = IO.readLines("http://localhost:9666/test");
    assertLines(lines);

}

プロキシ キャッシュ テストは次のとおりです。

public static class ProxyLoader {
    private static final String DATA_FILE = "./files/proxy.txt";


    private List<Proxy> proxyList = Collections.EMPTY_LIST;
    private final String dataFile;

    public ProxyLoader() {
        this.dataFile = DATA_FILE;
        init();
    }

    public ProxyLoader(String dataFile) {
        this.dataFile = DATA_FILE;
        init();
    }

    private void init() {
        List <String> lines = IO.readLines(dataFile);
        proxyList = new ArrayList<>(lines.size());

        for (String line : lines) {
            proxyList.add(Proxy.createProxy(line));
        }
    }

    public String getDataFile() {
        return this.dataFile;
    }

    public static List<Proxy> loadProxies() {
            return new ProxyLoader().getProxyList();
    }

    public List<Proxy> getProxyList() {
        return proxyList;
    }

}

public static class Proxy {
    private final String address;
    private final int port;

    public Proxy(String address, int port) {
        this.address = address;
        this.port = port;
    }

    public static Proxy createProxy(String line) {
        String[] lineSplit = line.split(":");
        String address = lineSplit[0];
        int port =  parseInt(lineSplit[1]);
        return new Proxy(address, port);
    }

    public String getAddress() {
        return address;
    }

    public int getPort() {
        return port;
    }
}


public static final class Proxy2 {
    private final String address;
    private final int port;
    private static final String DATA_FILE = "./files/proxy.txt";

    private static final Pattern addressPattern = Pattern.compile("^(\\d{1,3}[.]{1}){3}[0-9]{1,3}$");

    private Proxy2(String address, int port) {

        /* Validate address in not null.*/
        Objects.requireNonNull(address, "address should not be null");

        /* Validate port is in range. */
        if (port < 1 || port > 65535) {
            throw new IllegalArgumentException("Port is not in range port=" + port);
        }

        /* Validate address is of the form 123.12.1.5 .*/
        if (!addressPattern.matcher(address).matches()) {
            throw new IllegalArgumentException("Invalid Inet address");
        }

        /* Now initialize our address and port. */
        this.address = address;
        this.port = port;
    }

    private static Proxy2 createProxy(String line) {
        String[] lineSplit = line.split(":");
        String address = lineSplit[0];
        int port =  parseInt(lineSplit[1]);
        return new Proxy2(address, port);
    }

    public final String getAddress() {
        return address;
    }

    public final int getPort() {
        return port;
    }

    public static List<Proxy2> loadProxies() {
        List <String> lines = IO.readLines(DATA_FILE);
        List<Proxy2> proxyList  = new ArrayList<>(lines.size());

        for (String line : lines) {
            proxyList.add(createProxy(line));
        }
        return proxyList;
    }

}

@Test public void proxyTest() {
    List<Proxy> proxyList = ProxyLoader.loadProxies();
    assertEquals(
            5, len(proxyList)
    );


    assertEquals(
            "127.0.0.1", idx(proxyList, 0).getAddress()
    );



    assertEquals(
            8080, idx(proxyList, 0).getPort()
    );


    //192.55.55.57:9091
    assertEquals(
            "192.55.55.57", idx(proxyList, -1).getAddress()
    );



    assertEquals(
            9091, idx(proxyList, -1).getPort()
    );


}

実際のプロキシ キャッシュ テストは次のとおりです。

@Test public void proxyTest2() {
    List<Proxy2> proxyList = Proxy2.loadProxies();
    assertEquals(
            5, len(proxyList)
    );


    assertEquals(
            "127.0.0.1", idx(proxyList, 0).getAddress()
    );



    assertEquals(
            8080, idx(proxyList, 0).getPort()
    );


    //192.55.55.57:9091
    assertEquals(
            "192.55.55.57", idx(proxyList, -1).getAddress()
    );



    assertEquals(
            9091, idx(proxyList, -1).getPort()
    );


}

}

この例とこのユーティリティ クラスのすべてのソース コードは、次の場所で確認できます。

https://github.com/RichardHightower/boon

https://github.com/RichardHightower/boon/blob/master/src/main/java/org/boon/utils/IO.java

または、私に会いに来てください:

http://rick-hightower.blogspot.com/

于 2013-10-17T03:44:07.057 に答える
1

コードを整理することから始めましょう。問題を引き起こす可能性のある問題がかなりあります。ただし、プロキシ ファイルの関連部分がなければ、お客様の動作をテストまたは再現することはできません。単なるコード スニペットではなく、 SSCCEを作成して投稿することを検討してください。

  1. コードを適切にインデント/フォーマットします。
  2. これらのメソッドは必要ありません (すべきではありません) 。マルチスレッド環境での配列からの読み取りは安全であり、異なるスレッドでsynchronizedの複数のインスタンスを構築するべきではありません。つまり、 onは単に無駄です。ProxyLoadersynchronizedreadData()
  3. 大規模な配列を作成することは、このデータを格納する方法としては非常に貧弱です。大量の余分なメモリを割り当てるのは無駄であり、ロードされているファイルが設定した定数サイズより大きくなると、コードは失敗します。ArrayListやなどのスケーラブルなデータ構造を使用しMapます。
  4. アドレスとポートを別々の配列に格納します。オブジェクトを使用して両方の値を保持すると、メモリが節約され、データの不整合が防止されます。
  5. あなたのpublic int i変数は危険です-おそらく、ロードされた行の最大数を表すためにそれを使用していますが、これはメソッドの代わりに避けるべきですsize()-パブリックインスタンス変数として、クラスを使用する人は誰でもこの値を変更できi、貧弱です変数の名前maxは、より良いオプションです。
  6. readData()2回以上呼び出すと非常に奇妙なことが起こるため、公開したくない可能性があります( から始まるファイルを再度ロードしi、配列に重複データを入力します)。最良のアイデアは、データをコンストラクター (またはコンストラクターによって呼び出されるメソッド) に直接ロードすることprivateです。この方法では、作成されたインスタンスごとに 1 回だけファイルがロードされますProxyLoader
  7. 大規模な空の配列を作成し、lineSplitそれを の結果に置き換えていString.split()ます。これは紛らわしく無駄です。代わりにローカル変数を使用して分割線を保持してください。
  8. ファイルを読み取った後にファイルを閉じていないため、メモリ リークやその他のデータの不整合が発生する可能性があります。try-with-resources構文を使用すると、これが簡単になります。
  9. 文字列とポートを配置した後、配列全体をループし、残りのスロットを本質的にノイズで埋めます。これを行うことで何を達成しようとしているのかは不明ですが、お粗末な計画であることは確かです。

次の実装を提案します。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

public class ProxyLoader implements Iterable<ProxyLoader.Proxy> {
  // Remove DEFAULT_PROXY if not needed
  private static final Proxy DEFAULT_PROXY = new Proxy("127.0.0.1", 8080);
  private static final String DATA_FILE = "./proxy.txt";
  private ArrayList<Proxy> proxyList = new ArrayList<>();

  public ProxyLoader() {
    // Try-with-resources ensures file is closed safely and cleanly
    try(BufferedReader br = new BufferedReader(new FileReader(DATA_FILE))) {
      String line;
      while ((line = br.readLine()) != null) {
        String[] lineSplit = line.split(":");
        Proxy p = new Proxy(lineSplit[0], Integer.parseInt(lineSplit[1]));
        proxyList.add(p);
      }
    } catch (IOException e) {
      System.err.println("Failed to open/read "+DATA_FILE);
      e.printStackTrace(System.err);
    }
  }

  // If you request a positive index larger than the size of the file, it will return
  // DEFAULT_PROXY, since that's the behavior your original implementation
  // essentially did.  I'd suggest deleting DEFAULT_PROXY, having this method simply
  // return proxyList.get(i), and letting it fail if you request an invalid index.
  public Proxy getProxy(int i) {
    if(i < proxyList.size()) {
      return proxyList.get(i);
    } else {
      return DEFAULT_PROXY;
    }
  }

  // Lets you safely get the maximum index, without exposing the list directly
  public int getSize() {
    return proxyList.size();
  }

  // lets you run for(Proxy p : proxyLoader) { ... }
  @Override
  public Iterator<Proxy> iterator() {
    return proxyList.iterator();
  }

  // Inner static class just to hold data
  // can be pulled out into its own file if you prefer
  public static class Proxy {
    // note these values are public; since they're final, this is safe.
    // Using getters is more standard, but it adds a lot of boilerplate code
    // somewhat needlessly; for a simple case like this, public final should be fine.
    public final String address;
    public int port;

    public Proxy(String a, int p) {
      address = a;
      port = p;
    }
  }
}
于 2013-10-16T14:34:28.593 に答える