标签: default-method

与私有方法冲突时在接口中调用默认方法

考虑以下类层次结构.

class ClassA {
    private void hello() {
        System.out.println("Hello from A");
    }
}

interface Myinterface {
    default void hello() {
        System.out.println("Hello from Interface");
    }
}

class ClassB extends ClassA implements Myinterface {

}

public class Test {
    public static void main(String[] args) {
        ClassB b = new ClassB();
        b.hello();
    }
}
Run Code Online (Sandbox Code Playgroud)

运行该程序将出现以下错误:

Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.testing.ClassA.hello()V from class com.testing.Test
at com.testing.Test.main(Test.java:23)
Run Code Online (Sandbox Code Playgroud)
  1. 这都是因为我将ClassA.hello标记为私有.
  2. 如果我将ClassA.hello标记为protected或删除可见性修饰符(即使其成为默认范围),则它会显示编译器错误: The inherited method ClassA.hello() cannot hide the public abstract method in …

java java-8 default-method

39
推荐指数
1
解决办法
1310
查看次数

Java 8向类添加扩展/默认方法

我正在寻找一个等同于C#扩展方法功能的java.现在我一直在阅读Java 8的默认方法,但据我所知,我只能将它们添加到接口......

...是否有任何语言功能允许我为没有实现接口的最终类​​编写扩展方法?(我宁愿不用包装......)

java default-method

36
推荐指数
4
解决办法
3万
查看次数

为什么Java 8不允许使用非公共默认方法?

我们来举个例子:

public interface Testerface {

    default public String example() {
        return "Hello";
    }

}

public class Tester implements Testerface {

    @Override
    public String example() {
        return Testerface.super.example() + " world!";
    }


}

public class Internet {

    public static void main(String[] args) {
        System.out.println(new Tester().example());
    }

}
Run Code Online (Sandbox Code Playgroud)

简单地说,这将打印出来Hello world!.但是说我正在使用返回值做其他事情Testerface#example,例如初始化数据文件并返回一个不应离开实现类的敏感内部值.为什么Java不允许在默认接口方法上使用访问修饰符?为什么它们不能被保护/私有并且可能被子类提升(类似于扩展父类的类如何为重写方法使用更可见的修饰符)?

一个常见的解决方案是转移到抽象类,但在我的特定情况下,我有一个枚举接口,所以这里不适用.我想它或者被忽略了,或者因为接口背后的原始想法是它们是可用方法的"契约",但我想我想要输入关于这个的内容.

我读过" 为什么"最终"在Java 8接口方法中不允许? ",其中指出:

默认方法的基本思想是:它是具有默认实现的接口方法,派生类可以提供更具体的实现

对我来说听起来就像可见性根本不会破坏那个方面.

与链接的问题一样,因为它看起来很难被关闭,所以在这个问题上会得到权威的答案,而不是基于意见的答案.

java java-8 default-method

31
推荐指数
1
解决办法
5624
查看次数

扩展其他接口的默认方法和接口

假设有两个接口Interface1,Interface2其中Interface2扩展Interface1.

interface Interface1 {

    default void method() {
        System.out.println("1");
    }

    // Other methods
}

interface Interface2 extends Interface1 {

    @Override
    default void method() {
        System.out.println("2");
    }

    // Other methods
}
Run Code Online (Sandbox Code Playgroud)

假设我想创建一个实现的类,Interface2但我想method()成为其中的版本Interface1.如果我写

class MyClass implements Interface1, Interface2 {

    public void method() {
        Interface1.super.method();
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:

默认超级调用中的错误类型限定符:冗余接口Interface1由Interface2扩展

可以通过创建第三个界面来解决这个问题:

interface Interface3 extends Interface1 {

    default void method() {
        Interface1.super.method();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后:

class MyClass implements Interface1, Interface2, Interface3 …
Run Code Online (Sandbox Code Playgroud)

java java-8 default-method

28
推荐指数
1
解决办法
878
查看次数

如何从动态代理显式调用默认方法?

由于Java 8接口可以有默认方法.我知道如何从实现方法中显式调用该方法,即(请参阅在Java中显式调用默认方法)

但是,如何在代理上使用反射显式调用默认方法?

例:

interface ExampleMixin {

  String getText();

  default void printInfo(){
    System.out.println(getText());
  }
}

class Example {

  public static void main(String... args) throws Exception {

    Object target = new Object();

    Map<String, BiFunction<Object, Object[], Object>> behavior = new HashMap<>();

    ExampleMixin dynamic =
            (ExampleMixin) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{ExampleMixin.class}, (Object proxy, Method method, Object[] arguments) -> {

                //custom mixin behavior
                if(behavior.containsKey(method.getName())) {
                    return behavior.get(method.getName()).apply(target, arguments);
                //default mixin behavior
                } else if (method.isDefault()) {
                    //this block throws java.lang.IllegalAccessException: no …
Run Code Online (Sandbox Code Playgroud)

java reflection java-8 default-method

27
推荐指数
3
解决办法
3439
查看次数

maven-plugin-plugin:描述符目标在文件和文件中失败

在开发maven插件时,构建打印错误:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-plugin-plugin:3.3:descriptor (default-descriptor) on project default-method-demo: Execution default-descriptor of goal org.apache.maven.plugins:maven-plugin-plugin:3.3:descriptor failed: syntax error @[8,1] in file:/full/path/to/project/default-method/src/main/java/org/example/Iface.java -> [Help 1]
Run Code Online (Sandbox Code Playgroud)

即使该文件Iface.java是可编译的.

Iface.java:

package org.example;

public interface Iface {
    default String getString() {
        return "string";
    }
}
Run Code Online (Sandbox Code Playgroud)

pom.xml

<packaging>maven-plugin</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.3</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>3.0.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.4</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)

是什么原因造成的?怎么修好?

maven-plugin maven java-8 default-method

22
推荐指数
1
解决办法
8758
查看次数

你能用mockito(1.10.17)在接口中使用默认方法吗?

我是mockito的忠实粉丝,不幸的是,对于我使用Java 8的一个项目,它失败了...

场景:

public final class MockTest
{
    @Test
    public void testDefaultMethodsWithMocks()
    {
        final Foo foo = mock(Foo.class);

        //when(foo.bar()).thenCallRealMethod();

        assertThat(foo.bar()).isEqualTo(42);
    }

    @FunctionalInterface
    private interface Foo
    {
        int foo();

        default int bar()
        {
            return 42;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,测试失败并foo.bar()返回0.

当我取消注释该when()行时,我得到一个堆栈跟踪...

java.lang.NoSuchMethodError: java.lang.Object.bar()I
    at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18)
Run Code Online (Sandbox Code Playgroud)

这是maven上最新的稳定版本; 谷歌搜索周围没有告诉我关于Java 8中这个新功能的模拟状态...

你能否以其他方式使其工作,而不是实现接口和spy()它们(这是有效的)?

java mockito java-8 default-method

21
推荐指数
3
解决办法
8299
查看次数

功能接口继承Quirk

我有一个我已经使用了一段时间的自定义界面,看起来像这样:

public interface Function<T, R> {
    R call(T input);
}
Run Code Online (Sandbox Code Playgroud)

我想用Java Function和Guava 来改进这个接口Function,同时保持它FunctionalInterface.我以为我有完美的安排:

@FunctionalInterface
public interface Function<T, R> extends
        java.util.function.Function<T, R>,
        com.google.common.base.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}
Run Code Online (Sandbox Code Playgroud)

两个超级apply()接口都声明了相同的方法,该方法已在我的界面中实现,只留下抽象call()方法.奇怪的是,它不会编译,告诉我

"@FunctionalInterface"注释无效; 函数<T,R>不是功能接口

更奇怪的是,以下变化编译得很好:

@FunctionalInterface
public interface Function<T, R> extends
        java.util.function.Function<T, R> {

    R call(T input);

    @Override
    default R apply(T input) {
        return call(input);
    }
}
Run Code Online (Sandbox Code Playgroud)

@FunctionalInterface
public interface Function<T, R> extends
        com.google.common.base.Function<T, R> …
Run Code Online (Sandbox Code Playgroud)

java lambda java-8 default-method functional-interface

19
推荐指数
1
解决办法
3084
查看次数

java8:处理默认方法

在编写加密实用程序类时,我遇到了以下方法的问题:

public static void destroy(Key key) throws DestroyFailedException {
    if(Destroyable.class.isInstance(key)) {
        ((Destroyable)key).destroy();
    }
}

@Test
public void destroySecretKeySpec() {
    byte[] rawKey = new byte[32];
    new SecureRandom().nextBytes(rawKey);
    try {
        destroy(new SecretKeySpec(rawKey , "AES"));
    } catch(DestroyFailedException e) {
        Assert.fail();
    }
}
Run Code Online (Sandbox Code Playgroud)

javax.crypto.spec.SecretKeySpec上述方法的特定情况下可以正常工作,java7因为SecretKeySpec(javadocs 7)没有实现Destroyable(javadocs 7)

现在使用java8SecretKeySpec(javadocs 8)已经被Destroyable(javadocs 8)和方法Destroyable#destroy现在default哪个很好,根据这个声明

默认方法使您能够向库的接口添加新功能,并确保与为这些接口的旧版本编写的代码的二进制兼容性.

然后代码编译没有任何问题,尽管类ScretKeySpec本身没有被更改,单独的接口SecretKey已经.

问题是oracle's jdk8destroy方法有以下实现:

public …
Run Code Online (Sandbox Code Playgroud)

java secret-key java-8 default-method

18
推荐指数
2
解决办法
791
查看次数

在JSP EL中使用接口默认方法时,"在类型上找不到属性"

请考虑以下界面:

public interface I {
    default String getProperty() {
        return "...";
    }
}
Run Code Online (Sandbox Code Playgroud)

和刚刚重用默认实现的实现类:

public final class C implements I {
    // empty
}
Run Code Online (Sandbox Code Playgroud)

每当C在JSP EL脚本上下文中使用实例时:

<jsp:useBean id = "c" class = "com.example.C" scope = "request"/>
${c.property}
Run Code Online (Sandbox Code Playgroud)

- 我收到了PropertyNotFoundException:

javax.el.PropertyNotFoundException: Property 'property' not found on type com.example.C
    javax.el.BeanELResolver$BeanProperties.get(BeanELResolver.java:268)
    javax.el.BeanELResolver$BeanProperties.access$300(BeanELResolver.java:221)
    javax.el.BeanELResolver.property(BeanELResolver.java:355)
    javax.el.BeanELResolver.getValue(BeanELResolver.java:95)
    org.apache.jasper.el.JasperELResolver.getValue(JasperELResolver.java:110)
    org.apache.el.parser.AstValue.getValue(AstValue.java:169)
    org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:184)
    org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:943)
    org.apache.jsp.index_jsp._jspService(index_jsp.java:225)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Run Code Online (Sandbox Code Playgroud)

我最初的想法Tomcat 6.0对于Java 1.8功能来说太旧了,但我很惊讶Tomcat 8.0也受到了影响.当然,我可以通过显式调用默认实现来解决这个问题:

    @Override
    public String getProperty() {
        return I.super.getProperty();
    }
Run Code Online (Sandbox Code Playgroud)

- …

java jsp el java-8 default-method

18
推荐指数
1
解决办法
1887
查看次数