2014-01-18 56 views
3

UPDATE2:我自己的適配器類版本,它只在構造函數中調用instanceof,並在flush()close()函數中使用(Java 1.5)增量(避免在對象構造之後需要任何反射或邏輯),包含在這篇文章的底部。 UPDATE1:馬克Baumbach寫了一個簡單的適配器,正是我所需要的。包括在下面。原來的問題如下。如何將java.lang.Appendable包裝到java.io.Writer中?


,需要一個java.lang.Appendable可以接受java.io.Writer,因爲Writer實現Appendable的功能。

另一種方式呢?我正在使用一個需要編寫器的函數,並且我正在嘗試創建另一個調用它的函數,它接受一個appendable並將它傳遞給原始編寫器函數。

我看到您可以擴展Writer,這是抽象的,並將所有write(...)函數重定向到其對應的append(...) -s。但是你也必須實現flush()close(),並且我很清楚如何將它們寫得乾乾淨淨,以便這個包裝類可以接受任何可追加。

我很驚訝沒有任何東西已經存在,無論是在web或stackoverflow中,還是在現有的庫中,解決這個問題。至少不是我能找到的。

我希望在這裏有一點指導。謝謝。


回答此問題的適配器代碼。寫由馬克·鮑姆巴赫(我自己的版本低於):

import java.io.Closeable; 
import java.io.Flushable; 
import java.io.IOException; 
import java.io.Writer; 

public class AppendableWriterAdapter extends Writer { 

     private Appendable appendable; 

     public AppendableWriterAdapter(Appendable appendable) { 
      this.appendable = appendable; 
     } 

     @Override 
     public void write(char[] cbuf, int off, int len) throws IOException { 
      appendable.append(String.valueOf(cbuf), off, len); 
     } 

     @Override 
     public void flush() throws IOException { 
      if (appendable instanceof Flushable) { 
        ((Flushable) appendable).flush(); 
      } 
     } 

     @Override 
     public void close() throws IOException { 
      flush(); 
      if (appendable instanceof Closeable) { 
        ((Closeable) appendable).close(); 
      } 
     } 

} 

這是我自己的版本的基礎上,Marc的,那也只是在構造函數中使用instanceof,並且在flush()一(Java 1.5中)三角洲和close()。這是爲了避免在對象構造之後使用任何邏輯或反射。這也被釋放爲gisthttps://gist.github.com/aliteralmind/8494917

這個類包含了演示,後面兩個什麼也不做的增量(一個Flushable,一個Closeable),主要功能(newWriterForAppendable(apbl)),然後將適配器類本身。

import java.io.Closeable; 
    import java.io.Flushable; 
    import java.io.IOException; 
    import java.io.Writer; 
/** 
    <P>{@code java NewWriterForAppendable}.</P> 
**/ 
public class NewWriterForAppendable { 
    /** 
     <P>Demonstrates {@code newWriterForAppendable(apbl)} for creating a new {@code Writer} that wraps around {@code System.out} (writes to the console).</P> 
    **/ 
    public static final void main(String[] igno_red) { 
     try { 
     NewWriterForAppendable.newWriterForAppendable(System.out).write("hello"); 
     } catch(IOException iox) { 
     throw new RuntimeException("WriterForAppendableXmpl", iox); 
     } 
    } 
    /** 
     <P>A {@code Flushable} whose {@code flush()} function does nothing. This is used by {@link #newWriterForAppendable(Appendable ap_bl) newWriterForAppendable}{@code (apbl)} as a (Java 1.5) delta.</P> 

     @see #newWriterForAppendable(Appendable) newWriterForAppendable(apbl) 
    **/ 
    public static final Flushable FLUSHABLE_DO_NOTHING = new Flushable() { 
     public void flush() { 
     } 
    }; 
    /** 
     <P>A {@code Closeable} whose {@code close()} function does nothing. This is used by {@link #newWriterForAppendable(Appendable ap_bl) newWriterForAppendable}{@code (apbl)} as a (Java 1.5) delta.</P> 

     @see #newWriterForAppendable(Appendable) newWriterForAppendable(apbl) 
    **/ 
    public static final Closeable CLOSEABLE_DO_NOTHING = new Closeable() { 
     public void close() { 
     } 
    }; 
    /** 
     <P>Creates a new {@code java.io.Writer} that wraps around a {@code java.lang.Appendable}. It properly {@link java.io.Writer#flush() flush}es and {@link java.io.Writer#close() close}s appendables that happened to also be {@link java.io.Flushable}s and/or {@link java.io.Closeable Closeable}s. This uses {@code instanceof} only in the constructor, and a delta in {@code flush()} and {@code close()}, which avoids having to use any logic or reflection after object construction.</P> 

     <P>This function is released as a <A HREF="https://gist.github.com/aliteralmind/8494917">gist</A>, and is an example of the <A HREF="http://en.wikipedia.org/wiki/Adapter_pattern#Object_Adapter_pattern">Object Adapter pattern</A>. Thanks to <A HREF="http://stackoverflow.com/users/1211906/marc-baumbach">Marc Baumbach</A> on <A HREF="http://stackoverflow.com">{@code stackoverflow}</A> for the assistance. See (viewed 1/18/2014) 
     <BR> &nbsp; &nbsp; <CODE><A HREF="http://stackoverflow.com/questions/21200421/how-to-wrap-a-java-lang-appendable-into-a-java-io-writer">http://stackoverflow.com/questions/21200421/how-to-wrap-a-java-lang-appendable-into-a-java-io-writer</A></CODE></P> 

     @return A new writer that uses an appendable to do its output. 
     @see #FLUSHABLE_DO_NOTHING 
     @see #CLOSEABLE_DO_NOTHING 
    **/ 
    public static final Writer newWriterForAppendable(Appendable ap_bl) { 
     return (new WFA(ap_bl)); 
    } 
    private NewWriterForAppendable() { 
     throw new IllegalStateException("constructor: Do not instantiate."); 
    } 
} 
class WFA extends Writer { 
    private final Appendable apbl; 
    private final Flushable flbl; 
    private final Closeable clbl; 
    public WFA(Appendable ap_bl) { 
     if(ap_bl == null) { 
     throw new NullPointerException("ap_bl"); 
     } 
     apbl = ap_bl; 

     //Avoids instanceof at every call to flush() and close() 
     flbl = (Flushable)((ap_bl instanceof Flushable) ? ap_bl 
     : NewWriterForAppendable.FLUSHABLE_DO_NOTHING); 
     clbl = (Closeable)((ap_bl instanceof Closeable) ? ap_bl 
     : NewWriterForAppendable.CLOSEABLE_DO_NOTHING); 
    } 
    @Override 
    public void write(char[] a_c, int i_ndexStart, int i_ndexEndX) throws IOException { 
     apbl.append(String.valueOf(a_c), i_ndexStart, i_ndexEndX); 
    } 
    @Override 
    public Writer append(char c_c) throws IOException { 
     apbl.append(c_c); 
     return this; 
    } 
    @Override 
    public Writer append(CharSequence c_q) throws IOException { 
     apbl.append(c_q); 
     return this; 
    } 
    @Override 
    public Writer append(CharSequence c_q, int i_ndexStart, int i_ndexEndX) throws IOException { 
     apbl.append(c_q, i_ndexStart, i_ndexEndX); 
     return this; 
    } 
    @Override 
    public void flush() throws IOException { 
     flbl.flush(); 
    } 
    @Override 
    public void close() throws IOException { 
     flush(); 
     clbl.close(); 
    } 

} 
+0

Nitpick:對於'write(char [],int,int)'的impl,使用'apbl.append(String.valueOf(a_c, i_ndexStart,i_ndexEndX));'而不是'apbl.append(String.valueOf(a_c),i_ndexStart,i_ndexEndX);'?我認爲這會減少在start&end不是'0'和'a_c.length'的情況下複製的字節數。 – kevinarpe

+0

使用'CharBuffer.wrap(cbuf,off,len)'而不是'String.valueOf(cbuf,off,len)'會更高效,因爲這會爲現有的'cbuf'創建一個視圖,完全可以創建一個「CharSequence」。 – toKrause

回答

1

典型地,在Writer,所述flush()close()在那裏清除可能沒有被提交或發送到流的任何額外寫入。通過簡單地將所有write方法直接重定向到Appendable中的append方法,您將不必擔心flush()close(),除非您的Appendable執行Closeable和/或Flushable

一個很好的例子就是BufferedWriter。當你調用write()時,它可能不會立即將所有字節發送到最終輸出/流。一些字節可能不會被髮送,直到您flush()close()它。爲了絕對安全,我會在相應的方法中測試Appendable(如果它是CloseableFlushable)並轉換它並執行操作。

這是一個非常標準的設計模式,稱爲Adapter pattern

下面是可能是一個很好的實現這個適配器:http://pastebin.com/GcsxqQxj

+0

所以你只需將所有'write'重定向到'append',並創建空的'close'和'flush'功能,就是這樣!如果這是正確的,那就是*沒有*。非常感謝! – aliteralmind

+1

爲了絕對安全,在'close'和'flush'中,可以測試Appendable是否爲Closeable或Flusheable,並對其執行相應的操作。 –

+0

啊。所以似乎畢竟有一些反思。再次感謝。 – aliteralmind

0

可以接受任何Appendable,然後檢查它是否是一個Writer通過instanceof。然後做一個downcast並調用那個只接受Writer的函數。

例如:

public void myMethod(Appendable app) throws InvalidAppendableException { 

    if (app instanceof Writer) { 
     someObj.thatMethod((Writer) app); 
    } else { 
     throw new InvalidAppendableException(); 
    } 
} 
+0

在某些情況下,這是個好主意。但是,我會選擇使用非反射版本。 – aliteralmind

+0

原來,至少需要一些反射,所以這並不像我想的那麼遙遠! – aliteralmind

相關問題