Kotlin

Kotlinで同じ文字列が違うと判断されるバグを直す

Qiita初投稿です。よろしくおねがいします。
C#ばかり書いていましたが最近Kotlinをはじめました。いいですよね、Kotlin。擬人化したら絶対に可愛いです。

UDP通信をしようとしたら困った

簡単な文字列を受信し、ByteArray->Stringに変換してコンソールに写すだけです。(通信に関しては今回は触れません)
で、"finish"という文字列を受信したら通信をやめる、そんな感じにしたかったんです。したかったんです。

同じ文字列なのに等しいと判断されない…

うまくいかなかったときのソースコードは以下の通りです。

Main.kt
import Mylib.Udp.UdpConnection //自作のUdp通信クラス
import java.nio.charset.Charset

fun main(args: Array<String>)
{
    val port = 2222
    val bufferSize = 16
    val udp = UdpConnection(port, bufferSize)
    var received: String? = null

    println("Start")
    while (received != "finish")
    {
        received = udp.receive().toString(Charset.defaultCharset())
        println(received)
    }
}
UdpConnection
package Mylib.Udp

import java.io.FileWriter
import java.io.PrintWriter
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.nio.charset.Charset

class UdpConnection(private val port: Int, private val bufferSize:Int)
{
    fun receive(): ByteArray
    {
        val socket= DatagramSocket(port)
        val data = ByteArray(bufferSize)
        var packet: DatagramPacket? = null
        try
        {
            packet = DatagramPacket(data, data.size)
            socket.receive(packet)
        }
        catch (e: Exception)
        {
            println(e.message)
        }
        socket.close()
        return data
    }
}


これを実行中に"fnish"と三回送ったとします。私としてはコンソールには"Start"の後に一度だけ"finish"と出てきて終わっていただきたい。しかし、結果は…

Start
finish          
finish          
finish          

?????????なんですか??これ
いや、まぁ、文字化けしてるとかならわかるんですよ。
最初はJavaで有名な"=="と"equals"の違いが原因かと思いました。しかし、Kotlinでは参照先の比較は"==="で値の比較は"=="となっているため、今回は関係なさそうです。他にも文字コードや送信機などを疑ってみましたがどれも見当違い…

結局どうしたか

まず、以下の拡張関数を定義しました。

fun ByteArray.createString(packet: DatagramPacket) = String(this, 0, packet.length, Charset.defaultCharset())

そして上記のreceiveメソッドの型をString?に変更し、リターン部分を下記のように変更しました。

return if (packet != null) data.createString(packet); else null

結果、意図していた動作をしましたが、なぜ前のコードがダメだったのかはわかりません(わかる方いらっしゃいましたらご教示ください)

最後に

初投稿のため、拙い部分やおかしな部分もあると思いますが、閲覧頂きありがとうございます。関係ないですが、C#では下記のように簡単に実装できたため、Udp通信のハローワールド的なプログラムでつまずくと思いませんでした…

using System;
using System.Net.Sockets;
using System.Text;
class Program
{
    static void Main(string[] args)
    {
        var Receiver = new UdpClient(2222);
        var ReceivedStr = string.Empty;
        Console.WriteLine("Start");
        while ((ReceivedStr = Encoding.UTF8.GetString(Receiver.ReceiveAsync().Result.Buffer)) != "finish")
            Console.WriteLine(ReceivedStr);
    }
}

ここまで言ってJavaの使いやすいUdpライブラリがあったら恥ずかしいですね。(でもあったら使いたいです)