1. 程式人生 > >JDK1.8新特性介面預設方法

JDK1.8新特性介面預設方法

      從前幾天打開了買了1個半月的書《spring原始碼深度解析》(為自己找個冠冕堂皇的介面,忙工作沒時間看。。。。咳、咳!),在電腦上拉下了spring原始碼,檢視前幾頁的介紹資源載入時候的一些類和介面,終於配好了環境,隨便看下原始碼,印象最深的應該是Resource,畢竟書的開篇前幾頁就是介紹的這個。因為拉的最新版的spring看到了jdk1.8的特性在當中的使用,看到了介面中寫預設方法的特性了,下面是Resource的原始碼:

public interface Resource extends InputStreamSource {

   /**
    * Determine whether this resource actually exists in physical form.
* <p>This method performs a definitive existence check, whereas the * existence of a {@code Resource} handle only guarantees a valid * descriptor handle. */ boolean exists(); /** * Indicate whether the contents of this resource can be read via * {@link #getInputStream()}.
* <p>Will be {@code true} for typical resource descriptors; * note that actual content reading may still fail when attempted. * However, a value of {@code false} is a definitive indication * that the resource content cannot be read. * @see #getInputStream() */ default boolean
isReadable() { return true; } /** * Indicate whether this resource represents a handle with an open stream. * If {@code true}, the InputStream cannot be read multiple times, * and must be read and closed to avoid resource leaks. * <p>Will be {@code false} for typical resource descriptors. */ default boolean isOpen() { return false; } /** * Determine whether this resource represents a file in a file system. * A value of {@code true} strongly suggests (but does not guarantee) * that a {@link #getFile()} call will succeed. * <p>This is conservatively {@code false} by default. * @since 5.0 * @see #getFile() */ default boolean isFile() { return false; } /** * Return a URL handle for this resource. * @throws IOException if the resource cannot be resolved as URL, * i.e. if the resource is not available as descriptor */ URL getURL() throws IOException; /** * Return a URI handle for this resource. * @throws IOException if the resource cannot be resolved as URI, * i.e. if the resource is not available as descriptor * @since 2.5 */ URI getURI() throws IOException; /** * Return a File handle for this resource. * @throws java.io.FileNotFoundException if the resource cannot be resolved as * absolute file path, i.e. if the resource is not available in a file system * @throws IOException in case of general resolution/reading failures * @see #getInputStream() */ File getFile() throws IOException; /** * Return a {@link ReadableByteChannel}. * <p>It is expected that each call creates a <i>fresh</i> channel. * <p>The default implementation returns {@link Channels#newChannel(InputStream)} * with the result of {@link #getInputStream()}. * @return the byte channel for the underlying resource (must not be {@code null}) * @throws java.io.FileNotFoundException if the underlying resource doesn't exist * @throws IOException if the content channel could not be opened * @since 5.0 * @see #getInputStream() */ default ReadableByteChannel readableChannel() throws IOException { return Channels.newChannel(getInputStream()); } /** * Determine the content length for this resource. * @throws IOException if the resource cannot be resolved * (in the file system or as some other known physical resource type) */ long contentLength() throws IOException; /** * Determine the last-modified timestamp for this resource. * @throws IOException if the resource cannot be resolved * (in the file system or as some other known physical resource type) */ long lastModified() throws IOException; /** * Create a resource relative to this resource. * @param relativePath the relative path (relative to this resource) * @return the resource handle for the relative resource * @throws IOException if the relative resource cannot be determined */ Resource createRelative(String relativePath) throws IOException; /** * Determine a filename for this resource, i.e. typically the last * part of the path: for example, "myfile.txt". * <p>Returns {@code null} if this type of resource does not * have a filename. */ @Nullable String getFilename(); /** * Return a description for this resource, * to be used for error output when working with the resource. * <p>Implementations are also encouraged to return this value * from their {@code toString} method. * @see Object#toString() */ String getDescription(); }

        其中的isReadable(),isOpen(),isFile(),readableChannel(),都改使用了default方法,

        於是自己去寫了下幾個預設方法測試了一下:測試如下:

測試介面

public interface TestInterface {

    default void methods(){
        System.out.println("介面預設方法");
}
}

測試介面實現類

public class TestDefault implements TestInterface {
    
}

測試:

public class TestMain {

    public static void main(String[] args) {
        TestDefault testDefault = new TestDefault();
testDefault.methods();
}
}

輸出:


我們使用了預設方法之後實現類實現介面的時候可以不用重寫方法,不寫的時候呼叫的是介面的預設方法,

實現類重寫之後:

public class TestDefault implements TestInterface {

    @Override
public void methods() {
        System.out.println("實現類方法");
}
}

測試程式碼一樣,輸出結果如下:


是不是感覺和繼承的時候重寫一樣,那在重寫之後怎樣再去呼叫介面的預設方法呢,這個時候和繼承不太一樣,

程式碼如下:

public class TestDefault implements TestInterface {

    @Override
public void methods() {
        TestInterface.super.methods();
System.out.println("實現類方法");
}
}

測試程式碼一樣、輸出如下:


預設方法的出現可以減少大家在使用介面的時候,減少有多個實現類的時候的程式碼量,把多個實現類的公共程式碼提為預設方法寫在介面中,可以減少程式碼的重複量,