从前几天打开了买了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("实现类方法"); } }
测试代码一样、输出如下:
默认方法的出现可以减少大家在使用接口的时候,减少有多个实现类的时候的代码量,把多个实现类的公共代码提为默认方法写在接口中,可以减少代码的重复量,