方法局部内部类可以使用的合法修饰符之一是abstract。
例如:
public class Outer {
public void method(){
abstract class Inner{
}
}
}
有什么情况下您会真正使用它?
您必须在SCJP考试中了解这个。
方法局部内部类可以使用的合法修饰符之一是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();
}
}
但我想象不出真实的使用场景。
在我看来,这个功能没有实际用途。虽然有几种可能的滥用方式,但还有许多其他编写糟糕代码的方法,您不需要学习这种方法。 :D
每当您尝试利用抽象方法本地类时,您需要定义至少两个具体的方法内部类。这意味着您最终会得到一个包含至少三个类的方法,该方法变得相当冗长,这是一种相当糟糕的风格。
您必须为SCJP考试掌握这些内容。
我真的希望不需要。方法本地内部类已经足够无用,被认为是一个边角案例(您应该理解它们,但可能永远不会使用它们)。
在我看来,一个在考试中问这个问题的人对Java的理解存在严重误解。由于(缺少方法文字),局部类无法从外部访问,因此不能有可访问性修饰符。可以有abstract
和final
修饰符,因为没有理由禁止它们。允许它们有很好的理由:正交性和最小惊奇原则。
有没有任何情况下你会实际使用它?
令 S1 表示所有需要抽象类的情况。
令 S2 表示所有需要局部类的情况。
通过检查 S1 ∩ S2 可以找到你问题的答案。
相关问题:
abstract
。 - Aaron Digulla我认为在某些情况下,减小方法的范围可能会很有用。
例如,在单元测试中我会使用它。有时您需要一个实用程序方法来减少测试的冗长性。但是这个实用程序方法可能与当前测试数据集相关,并且无法在此测试之外重复使用。
@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 y a tres longtemps
doc2.setLocation(DocumentLocation.SAFE);
client.index(doc2);
//
final List<DateRange> facettedRanges = Arrays.<DateRange>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);
}
最后,我认为允许减少可见性的功能并不是无用的。
你可以构建一个完全正常工作的应用程序,而根本不使用封装,并且可以争论同样的事情,说私有修饰符是无用的...
但是,私有修饰符肯定比方法局部内部类更有用;)
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);
}
}
你可以像这样使用它。
请查看此页面上标题为“内部类的层次结构”的部分。
要点是您可以将内部类视为另一个需要被覆盖/实现的抽象成员。我不一定同意这种做法(我可能会单独定义内部类),但我在实际开发中也见过类似的情况。
以下是他们的示例代码:
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;
}
}
}
我能想象到唯一真正的用途是用于数据结构中的节点
这样,您可以区分方法和哨兵节点以及普通数据节点,这在递归算法中非常方便,而且您不必每次都进行空值检查。
不,抽象类(或一般的类)在方法内部没有什么好的用途。
只有当特定的方法需要特定的类并且还要实现它时,这才有意义。实际上,在您编写的数万亿个方法中,也许只会发生那种情况一次。