为什么使用方法本地抽象内部类

可以与方法本地内部类一起使用的合法修饰符之一是abstract。

例如:

public class Outer { public void method(){ abstract class Inner{ } } } 

你有实际使用它的情况吗?

你必须知道SCJP考试。

这是原始问题中的一些无效假设。 某些东西是合法/有效的Java并不意味着它是您需要使用或需要知道的东西。

我不记得SCJP包含奇怪的案例问题。

我试图提出一个案例,我将使用在方法中声明的抽象类,但是一切看起来都很奇怪,并且设计糟糕。 这是一个我想出的代码示例(仍然是糟糕的代码设计恕我直言)

 public class BatchExecutor { public static enum ResultNotification { JMS, MAIL }; public Runnable createRunnable(ResultNotification type) { abstract class Prototype implements Runnable { public void run() { performBusinessLogic(); publishResult(); } abstract void publishResult(); } switch (type) { case JMS: { return new Prototype() { void publishResult() { //Post result to JMS } }; } case MAIL: { return new Prototype() { void publishResult() { //Post result to MAIL } }; } } return null; } private void performBusinessLogic() { //Some business logic } } 

我只能在这种情况下思考

 class Outer { public void method() { abstract class A { void bar(){} abstract void foo(); } class B extends A { @Override void foo() { } } final class C extends A { @Override void foo() { } } A a1 = new B(); A a2 = new C(); } } 

但我无法想象真正的用法

你有实际使用它的情况吗?

  1. 设S 1表示您需要抽象类的所有情况。

  2. 设S 2表示您需要本地课程的所有情况。

  3. 通过检查S1∩S2可以找到你的问题的答案

相关问题:

  • 方法本地内部类在Java中提供了什么好处?
  • 使用Java [接口/抽象类]

澄清:我的观点是这两个特征( 抽象类本地类 )是该语言的两个完全正交的特征。 了解每个function何时有用是了解它们何时同时有用的关键。

恕我直言,这个function没有实际用途。 有一些可能的滥用,但还有许多其他方法来编写错误的代码,你不需要学习这个。 :d

每当您尝试使用抽象方法本地类时,您都需要定义至少两个具体的方法 – 内部类。 这意味着你最终得到一个至少包含三个类的方法,这个方法变得很长,而且风格很糟糕。

你必须知道SCJP考试。

我真的希望不是。 方法本地内部类已经无用了被认为是一个极端情况(你应该理解它们但可能永远不会使用它们)。

恕我直言,一个在考试中提出这个问题的人误解了Java。 本地类上不能有可访问性修饰符,因为(缺少方法文字)无论如何都无法从外部访问类。 可以有abstractfinal修饰符,因为没有理由禁止它们。 有充分理由允许它们: 正交性和最小惊讶原则 。

您可以在这里使用http://java-questions.com/InnerClass_interview_questions.html

这说

在方法内部声明的内部类称为方法本地内部类。 方法本地内部类只能声明为final或abstract。 方法本地类只能在声明为final时访问全局变量或方法局部变量

即,您可以在内部调用中声明静态变量,并在方法中使用它们。

编辑:为何抽象:

因为如果你不想创建内部类的对象。 如果在方法中创建对象,则它将存储在堆中,即使方法执行完成也不会释放它,因为从该方法返回时此对象可能存在外部引用。

所以这取决于您是否要创建实例。 如果要创建然后使用final修饰符。

我能想象的唯一真正用途是数据结构中的节点

这样你可以区分方法与前哨节点和普通数据节点,这在递归算法中非常方便,你不必每次都进行空值检查

不,在方法内部没有很好地使用抽象类(或一般类)。

只有那个特定的方法需要那个特定的类并且也会实现它才有意义。 实际上,这种情况可能会发生在您编写的数万亿种方法中。

请查看此页面上标题为“内部类的层次结构”的部分。

要点是,您可以将内部类视为另一个需要重写/实现的抽象成员。 我不一定同意它(我可能只是单独定义内部类),但我在野外看到过这样的事情。

这是他们的示例代码:

 public abstract class BasicMonitorScreen { private Dimension resolution; public BasicMonitorScreen(final Dimension resolution) { this.resolution = resolution; } public Dimension getResolution( ) { return this.resolution; } protected abstract class PixelPoint { private int x; private int y; public PixelPoint(final int x, final int y) { this.x = x; this.y = y; } public int getX( ) { return x; } public int getY( ) { return y; } } } public class ColorMonitorScreen extends BasicMonitorScreen { public ColorMonitorScreen(final Dimension resolution) { super(resolution); } protected class ColorPixelPoint extends PixelPoint { private Color color; public ColorPixelPoint(final int x, final int y, final Color color) { super(x, y); this.color = color; } public Color getColor( ) { return this.color; } } } 

我认为在某些条件下缩小方法的范围会很有用。

例如,我在unit testing中使用它。 有时您需要一种实用方法来降低测试的详细程度。 但是这种实用方法可能与当前的测试数据集有关,并且不能在该测试之外重复使用。

  @Test public void facetting_is_impacted_by_filtering() { // given String userId = "cd01d6b08bc29b012789ff0d05f8e8f1"; DocumentSolrClient client = solrClientsHolder.getDocumentClient(userId); // final SolrDocument doc1 = createDocument(userId); doc1.setAuthorName("AuthorName1"); doc1.setType("Type1"); doc1.setUserTags(Arrays.asList("UserTag1", "UserTag1bis","UserTag1bisbis")); doc1.setSenderTags(Arrays.asList("SenderTag1", "SenderTag1bis")); doc1.setCreationDate( new Date(EnumDateRange.CURRENT_DAY.getBegin().getTime()+1000) ); doc1.setLocation(DocumentLocation.INBOX); client.index(doc1); // final SolrDocument doc2 = createDocument(userId); doc2.setAuthorName("AuthorName2"); doc2.setType("Type2"); doc2.setUserTags(Arrays.asList("UserTag2")); doc2.setSenderTags(Arrays.asList("SenderTag2")); doc2.setCreationDate( new Date(1000) ); // cree il ya tres longtemps doc2.setLocation(DocumentLocation.SAFE); client.index(doc2); // final List facettedRanges = Arrays.asList( EnumDateRange.CURRENT_DAY, EnumDateRange.CURRENT_YEAR, EnumDateRange.BEFORE_CURRENT_YEAR ); class TestUtils { ApiSearchRequest baseFacettingRequest(String userId) { ApiSearchRequest req = new ApiSearchRequest(userId); req.setDocumentTypeFacets(true); req.setSenderNameFacets(true); req.setSenderTagsFacets(true); req.setUserTagsFacets(true); req.addDateCreationFacets(facettedRanges); return req; } void assertDoc1FacettingResult(ApiSearchResponse res) { assertThat(res.getDocuments().size()).isEqualTo(1); assertThat(res.getDocumentTypeFacets().get().getCounts()).hasSize(1); assertThat(res.getSenderNameFacets().get().getCounts()).hasSize(1); assertThat(res.getSenderTagsFacets().get().getCounts()).hasSize(2); assertThat(res.getUserTagsFacets().get().getCounts()).hasSize(3); assertThat(res.getDateCreationFacets().get().getCounts()).isEqualTo( computeExpectedDateFacettingResult( Arrays.asList(doc1),facettedRanges) ); } void assertDoc2FacettingResult(ApiSearchResponse res) { assertThat(res.getDocuments().size()).isEqualTo(1); assertThat(res.getDocumentTypeFacets().get().getCounts()).hasSize(1); assertThat(res.getSenderNameFacets().get().getCounts()).hasSize(1); assertThat(res.getSenderTagsFacets().get().getCounts()).hasSize(1); assertThat(res.getUserTagsFacets().get().getCounts()).hasSize(1); assertThat(res.getDateCreationFacets().get().getCounts()).isEqualTo( computeExpectedDateFacettingResult( Arrays.asList(doc2),facettedRanges) ); } } TestUtils utils = new TestUtils(); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // when ApiSearchRequest req = utils.baseFacettingRequest(userId); ApiSearchResponse res = documentSearchService.search(req); // then assertThat(res.getDocuments().size()).isEqualTo(2); assertThat(res.getDocumentTypeFacets().get().getCounts()).hasSize(2); assertThat(res.getSenderNameFacets().get().getCounts()).hasSize(2); assertThat(res.getSenderTagsFacets().get().getCounts()).hasSize(3); assertThat(res.getUserTagsFacets().get().getCounts()).hasSize(4); assertThat(res.getDateCreationFacets().get().getCounts()).isEqualTo( computeExpectedDateFacettingResult( Arrays.asList(doc1,doc2),facettedRanges) ); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // when req = utils.baseFacettingRequest(userId); req.addLocation(DocumentLocation.SAFE); res = documentSearchService.search(req); // then utils.assertDoc2FacettingResult(res); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // when req = utils.baseFacettingRequest(userId); req.addUserTag("UserTag1"); res = documentSearchService.search(req); // then utils.assertDoc1FacettingResult(res); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // when req = utils.baseFacettingRequest(userId); req.addSenderTag("SenderTag2"); res = documentSearchService.search(req); // then utils.assertDoc2FacettingResult(res); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // when req = utils.baseFacettingRequest(userId); req.setDocumentType("Type1"); res = documentSearchService.search(req); // then utils.assertDoc1FacettingResult(res); } 

在这个现实生活中,我可以做一个常规的内部类,但有人可能会试图在其他测试中重用它,而它不是为了设计的。

顺便说一下,您会注意到在实用程序类中直接“捕获”测试中的数据集构建的能力。 使用常规内部类,如果没有在测试之外创建测试特定数据集,它就无法工作……所以你最终会得到很多与其他测试共享的东西,而它们只被使用了一部分(应该被使用) 。


最后,我不认为允许降低能见度的function是无用的。

你可以在不使用封装的情况下构建一个完美的应用程序,并且可以争论相同的事情,说私有修饰符是无用的……

但是,是的,私有修饰符肯定比方法本地内部类更有用;)

 package dto; public class Outer { public void method(int x, int y){ abstract class Inner{ abstract void performAction(int x,int y); } class InnnerA extends Inner{ @Override void performAction(int x,int y) { int z =x+y; System.out.println("addition :" + z); } } class InnnerB extends Inner{ @Override void performAction(int x,int y) { System.out.println("multiply :"+x*y); } } Inner inner1 = new InnnerA(); inner1.performAction(x,y); Inner inner2 = new InnnerB(); inner2.performAction(x,y); } public static void main(String args[]){ Outer outer = new Outer(); outer.method(10,20); } } 

你可以像这样使用它。