[英]Does BufferedWriter's write(String S) method actually buffer?
[英]Why BufferedWriter write() method does not autocast to String
我來到了Java的這種行為,對我來說似乎有點奇怪。
在檢查這篇文章時,我確實意識到BufferedWriter
的write()
方法不適用於Long
對象:
BufferedWriter writer = new BufferedWriter(new FileWriter(outFile));
Long l1 = new Long(1);
writer.write(l1); // <- this won't work as it is
雖然我經常使用BufferedWriter
,但它的格式可以使用分隔符寫入多個值:
writer.write(l1 + ","); //<- this works fine.
因此,我猜想起區別的部分是+ ","
部分,它實際上將l1.toString() + ","
提供給BufferedWriter
作為輸入。
我的問題是為什么Java在這些情況下不將自動廣播應用於String
。 我的意思是,既然write()
期望出現什么問題:
BufferedWriter
實現的方法中的int
Writer
類中的String
。 預期結果是否會有歧義?
在類似的(根據我的看法System.out.print()
, PrintStream
System.out.print()
可以完美地工作:
System.out.println(l1); // <- this works fine
PrintStream
也不包含println(Long)
方法。 這是否意味着首先將其轉換為long
,然后使用此方法( out.print(long)
),所以對於BufferedWriter
而言,此步驟無法完成?
在Java中,沒有“自動廣播到String
”這樣的東西。 當在字符串上下文中使用“ +
”運算符時,操作數將轉換為字符串。 這意味着您要查找的隱式轉換僅在“ +
”運算符的上下文中發生。
Writer
和BufferedWriter
中可用的write()
方法為:
void write(char[] cbuf)
-寫入一個字符數組。 void write(char[] cbuf, int off, int len)
-寫入字符數組的一部分。 void write(int c)
-寫一個字符。 void write(String str)
-寫入一個字符串。 void write(String str, int off, int len)
-寫入字符串的一部分。 如果您想編寫其他內容,則將無法正常工作,因為write()
方法不會因您要查找的變量而超載。
您正在尋找的是這樣的:
void print(Object o)
-編寫一個對象,通過調用其toString()
方法將其轉換為字符串,除非o == null
,在這種情況下將寫入字符串"null"
。 您可以使用包含此類方法的PrintWriter
包裝BufferedWriter
。 尋找名為print
而不是write
。 您會看到PrintWriter
(就此而言, PrintStream
)包含許多針對各種類型的重載方法,以便從字面上可以打印任何內容,而不僅僅是String
和char
acters。
因此,您的代碼如下所示:
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
Long l1 = new Long(1);
writer.print(l1); // <- this works.
PS: PrintStream
和PrintWriter
包含兩種可以使用的方法: println(long)
/ print(long)
和println(Object)
/ print(Object)
。 請參閱http://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html和http://docs.oracle.com/javase/8/docs/api/java/io/PrintWriter.html
。 Java可以在使用println(Object)
和println(long)
之間“選擇”。 如果兩者均可用,則Java使用println(Object)
,如果我們對此稍作考慮,則很清楚原因。 long
具有2 ^ 32個可能的值,但是Long
(從邏輯角度來看)具有2 ^ 32 + 1個可能的值,因為它也可能為null
。 如果我們用null
調用println(long)
,則會得到NullPointerException
因為(Long) null
無法成功拆箱到long
。 但是println(Object)
可以使用null
。 將諸如long
類的原始類型隱式轉換為諸如Long
類的對應對象的過程稱為自動裝箱,相反過程稱為取消裝箱。 如果有選擇,編譯器將避免拆箱。
PPS:在Java中, 重載意味着一個類或對象提供多個具有相同名稱但具有不同參數類型列表的方法。 編譯器通過將參數類型與候選方法的參數類型進行匹配來選擇正確的方法。 可能構造不明確的案例,即writer.write(null)
。 可以使用強制類型轉換或變量, writer.write((String) null)
或String s = null; writer.write(s);
來解決歧義String s = null; writer.write(s);
String s = null; writer.write(s);
。
Long l1 = new Long(1);
writer.write(l1.toString()); //-> It is possible
writer.write(l1 + ","); // here you concat the long with String it returns String
長+字符串->字符串。
BufferedWriter類沒有任何寫入Long的方法。
可能的寫入方法BufferedWriter
查看Java語言規范的第5.4節“字符串上下文” 。 它明確指出,“ +
”運算符在與字符串和其他對象一起使用時,將對那些其他非字符串對象使用字符串強制。
在我看來(基於評論)並且在Writer
類看來, Writer
類僅應編寫單個字符,這似乎很清楚。 因此,要求它打印一個整數值(長,字節,短還是其他)與該類的意圖背道而馳(通用對象也是如此)。 是的,您可以為它傳遞一個整數值,但該值實際上是一個char
而不是 int
因此它將打印char
值而不是int
值。
這一事實l1 + ","
的工作原理是,因為編譯器轉換這對一個String
對象(其Writer
然后轉換成字符數組和寫入String
值char
通過char
)。 請注意,調用Writer.write((int)(l1 + ','))
將產生“意外”結果)。
如果要打印字符串表示形式,則應將BufferedWriter
包裝在PrintWriter
,即:
public static PrintWriter getPrintWriter(final BufferedWriter bw){
return new PrintWriter(bw);
}
我還應該指出,如果您要非常小心,則應使用OutputStreamWriter
並指定字符編碼或字符集(這實際上對於讀取文件而不是寫入文件更重要,即應使用InputStreamReader
進行讀取。文本文件)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.