简体   繁体   English

public方法在Java中返回私有类实例?

[英]public method returns private class instance in Java?

I have a method that returns an instance of a private class and I need access to its methods from a different package for unit testing. 我有一个方法返回私有类的实例,我需要从不同的包访问其方法进行单元测试。 These classes live in the same file. 这些类存在于同一个文件中。 It goes like this: 它是这样的:

file: A.java 档案:A.java

public class A{
    B b;
    public B getB(){
        return b;
    }  
    public setB(B b){
        this->b = b;
   }
}

class B{
    C c;
    public C getC(){
        return c;
    }
    public setC(C c){
        this->c = c;
   }
}

class C{
    public int getInt(){
        return 1;
    }
}

So... Basically the question is: are any of the methods in B or C reachable somehow? 所以...基本上问题是:B或C中的任何方法都能以某种方式到达吗? Am I obligated to place B and C in different files and make them public to accomplish that? 我是否有义务将B和C放在不同的文件中并将其公之于众?

It is best practice to ALWAYS put the source code for each top level class in a separate file. 最佳做法是始终将每个顶级类的源代码放在单独的文件中。 If you don't do this, you may run into difficulties with compiling, etc. 如果你不这样做,你可能会遇到编译困难等问题。

There is a separate issue of whether the classes B and C need to be public so that you can create unit tests. 还有一个问题是B类和C类是否需要public以便您可以创建单元测试。 I'd say it is probably a good idea, but there are a couple of ways around this: 我想这可能是一个好主意,但有几种方法可以解决这个问题:

  • If you put the unit tests in the same Java package as the classes A , B and C , then the classes (and their methods) will be visible to the unit tests. 如果将单元测试放在与ABC类相同的Java包中,则单元测试将显示类(及其方法)。

  • You could expose the methods by creating public subclasses of B and C for test purposes. 您可以通过创建BC public子类来公开方法以用于测试目的。 These have to be declare in the same Java package as the classes A , B and C . 这些必须在与ABC类相同的Java包中声明。

  • You could create instances of B and C and call methods on them using reflection. 您可以使用反射创建BC实例并在其上调用方法。 (But this is a lot of work for a unit test, and I would NOT recommend it!) (但这对于单元测试来说是很多工作,我不推荐它!)

Note that if you have separate source directory trees for your product code and your test code, you can put test classes into the same package as A , B and C without mixing up the codebases. 请注意,如果您的产品代码和测试代码具有单独的源目录树,则可以将测试类放入与ABC相同的包中,而不会混淆代码库。 When you build for production / release, you just leave the classes in the test tree out of the build. 在为生产/发布构建时,只需将测试树中的类保留在构建之外。


By the way, in your example the classes B and C are "package private" rather than "private". 顺便说一下,在你的例子中,类BC是“包私有”而不是“私有”。 Unit testing a real "private" class is a whole different problem. 单元测试一个真正的“私人”类是一个完全不同的问题。

You want to use Reflection to test private methods with unit testing. 您希望使用Reflection来使用单元测试来测试私有方法。 You can read more here(see answer): 你可以在这里阅读更多内容(见答案):

How do I test a class that has private methods, fields or inner classes? 如何测试具有私有方法,字段或内部类的类?

Yes, you can use reflection to invoke all methods in any instance of B or C anywhere, but this, from my POV, is a hack rather than a technique. 是的,您可以使用反射在任何地方调用BC的任何实例中的所有方法,但是,从我的POV来看,这是一种黑客而不是技术。

Otherwise, class B and C are not exposed outside your A.class . 否则, B类和C类不会暴露在A.class之外。

Technically the classes are protected; 从技术上讲,课程受到保护; so as long as classes that call getB and getC are within the same package you won't have any issues. 因此,只要调用getB和getC的类在同一个包中,就不会有任何问题。 If from another package you tried to run GetB GetC you are going to see some issues because your other package will not be able to access the actual class. 如果你试图运行GetB GetC的另一个软件包,你会看到一些问题,因为你的其他软件包将无法访问实际的类。

Here TestProt CANNOT be imported since it is protected in the tester2 package. 这里不能导入TestProt,因为它在tester2包中受到保护。 FILE1: FILE1:

package tester; 
import tester2.Test; 
public class Testing {   
  public Testing() {
    Test t = new Test();
    TestProt p = t.prot();   
  } 
}

FILE2: FILE2:

package tester2;
public class Test {
  public TestProt prot() {
    return new TestProt();
  } 
}

class TestProt{
  public TestProt() {
  } 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM