可以与方法本地内部类一起使用的合法修饰符之一是abstract。
例如:
public class Outer {
public void method(){
abstract class Inner{
}
}
}
有没有你真正使用它的情况?
你必须知道SCJP考试。
答案 0 :(得分:12)
原始问题中的一些无效假设。某些东西是合法/有效的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
}
}
答案 1 :(得分:9)
我只能在这种情况下思考
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();
}
}
但我无法想象真正的用法
答案 2 :(得分:7)
您是否有实际使用此功能的情况?
设S 1 表示您需要抽象类的所有情况。
设S 2 表示您需要本地课程的所有情况。
通过检查S 1 ∩S 2
相关问题:
澄清:我的观点是这两个功能(抽象类和本地类)是该语言的两个完全正交的功能。了解每个功能何时有用是了解它们何时同时有用的关键。
答案 3 :(得分:6)
每当您尝试使用抽象方法本地类时,您需要至少定义两个具体的方法 - 内部类。这意味着你最终会得到一个至少包含三个类的方法,这个方法会很长,并且风格很糟糕。
你必须知道SCJP考试。
我真的希望不是。方法本地内部类已经无用了被认为是一个极端情况(你应该理解它们但可能永远不会使用它们)。
恕我直言,一个在考试中提出这个问题的人误解了Java。在本地类上不能有可访问性修饰符,因为(缺少方法文字)无论如何都无法从外部访问类。可以有abstract
和final
修饰符,因为没有理由禁止它们。有充分的理由允许他们:orthogonality和Principle of least astonishment。
答案 4 :(得分:1)
您可以在此处使用http://java-questions.com/InnerClass_interview_questions.html
说
在方法内声明的内部类称为方法本地内部类。方法本地内部类只能声明为final或abstract。方法本地类只能在声明为final
时访问全局变量或方法局部变量即您可以在内部调用中声明静态变量,并在方法中使用它们。
编辑:为何抽象:
因为如果你不想创建内部类的对象。如果在方法中创建对象,那么它将存储在堆中,即使方法执行完成也不会释放它,因为当从该方法返回时,该对象可能存在外部引用。
因此,这取决于您是否要创建实例。如果您想创建,请使用最终修饰符。
答案 5 :(得分:0)
我能想到的唯一真正用途是数据结构中的节点
通过这种方式,您可以将方法与标记节点和普通数据节点区分开来,这在递归算法中非常方便,并且您不必每次都进行空检查
答案 6 :(得分:0)
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);
}
}
你可以像这样使用它。
答案 7 :(得分:0)
不,在方法内部没有很好地使用抽象类(或一般类)。
只有那个特定的方法需要那个特定的类并且也会实现它才有意义。实际上,这种情况可能会发生在您编写的数万亿方法中。
答案 8 :(得分:0)
查看this page上标题为“内部类的层次结构”的部分。
要点是,您可以将内部类视为另一个需要重写/实现的抽象成员。我不一定同意它(我可能只是单独定义内部类),但我在野外看到过这样的事情。
这是他们的示例代码:
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;
}
}
}
答案 9 :(得分:0)
我认为在某些条件下减少方法的范围会很有用。
例如,我在单元测试中使用它。有时您需要一种实用方法来降低测试的详细程度。但是这种实用方法可能与当前的测试数据集有关,并且不能在该测试之外重复使用。
@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);
}
在这个现实生活中,我可以做一个常规的内部类,但有人可能会试图在其他测试中重复使用它,而它不是为了设计的。
顺便说一句,您会注意到能够直接在实用程序类中“捕获”测试中的数据集构建。使用常规内部类,如果没有在测试之外创建测试特定数据集,它就无法工作......所以你最终会得到很多与其他测试共享的东西,而它们只被使用了一部分(应该被使用) 。
最后,我认为不允许降低能见度的功能是无用的。
你可以在不使用封装的情况下构建一个完美的应用程序,并且可以争论相同的事情,说私有修饰符是无用的......
但是,是的,私有修饰符肯定比方法本地内部类更有用;)