关于java:interfaces方法与类方法

interfaces methods vs classes methods

在Java-8中,我们可以有一种方法,例如,通过多种方式屏蔽字符串:

接口实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public interface StringUtil {
    static String maskString(String strText, int start, int end, char maskChar)
            throws Exception{

        if( Strings.isNullOrEmpty(strText))
            return"";

        if(start < 0)
            start = 0;

        if( end > strText.length() )
            end = strText.length();

        if(start > end)
            throw new Exception("End index cannot be greater than start index");

        int maskLength = end - start;

        if(maskLength == 0)
            return strText;

        StringBuilder sbMaskString = new StringBuilder(maskLength);

        for(int i = 0; i < maskLength; i++){
            sbMaskString.append(maskChar);
        }

        return strText.substring(0, start)
                + sbMaskString.toString()
                + strText.substring(start + maskLength);
    }
}

可通过以下方式访问:

1
StringUtil.maskString("52418100", 2, 4, 'x')

现在可以通过类实现相同的功能,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class StringUtil {

    public String maskString(String strText, int start, int end, char maskChar)
                throws Exception{

            if( Strings.isNullOrEmpty(strText))
                return"";

            if(start < 0)
                start = 0;

            if( end > strText.length() )
                end = strText.length();

            if(start > end)
                throw new Exception("End index cannot be greater than start index");

            int maskLength = end - start;

            if(maskLength == 0)
                return strText;

            StringBuilder sbMaskString = new StringBuilder(maskLength);

            for(int i = 0; i < maskLength; i++){
                sbMaskString.append(maskChar);
            }

            return strText.substring(0, start)
                    + sbMaskString.toString()
                    + strText.substring(start + maskLength);
    }
}

这可以访问为:

1
2
StringUtil su = new StringUtil()
String mask = su.maskString("52418100", 2, 4, 'x')

问题:

在哪种情况下必须优先选择哪一种?到目前为止,我了解到interface函数是不可通过mock测试的,所以我必须在接口函数的顶部有一个包装函数,简而言之,它不支持单元测试,而且作为static函数,您不能重写接口方法。

那么,如果您有一个编写函数的选项,您会考虑其他哪些用例呢?


对于任何明确开发的实用程序,我建议使用类。在Java中,EDCOX1 4是有特殊用途的。这些都是实用方法,需要供应商为其提供实现(还记得吗?-An interface is a contract between Vendor and User

例如,如果您正在使用任何第三方库,并且某一天供应商引入了一个新的实用程序功能,那么要么所有客户都必须在接口内重写该方法,要么只是供应商添加了一个静态默认方法。这样,新库的代码仍然向后兼容(at binary code level)。

准确地说,功能接口的用法和用途在Oracle文档中有很好的解释,如下所示:

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

更多信息,您可以在这里阅读官方文档。

此外,考虑到这一目的,在编写这种方法之前,永远不需要在您的端测试默认方法。如果实用方法很复杂,就应该测试它。这些实用程序当然可以进行集成测试。此外,正如您所说,您可以编写接口的简单实现并测试这些东西。这与测试abstract class类似。请阅读此处了解更多详细信息。


首先,为了在接口中定义方法,需要使用默认关键字。通常,方法不在接口中定义——这可能是类和接口之间最大的区别。

现在,当您想要保证跨无关类共享功能时,可以使用接口。例如,Serializable接口保证实现此接口的任何类都是Serializable。我不想解释"序列化"在这里意味着什么,但我的想法是,不要让数百个类在混乱的子类树中扩展抽象的可序列化类,您可以简单地实现可序列化,并使用多态性的力量将类称为Serializable。请在此处查看更多精彩信息:https://www.tutorialspoint.com/java/java_interfaces.htm

在您的例子中,您需要的是StringUtil类,而不是StringUtil接口。因为StringUtil只包含一个实用方法,所以您还需要使这个方法(maskstring())成为static