Java中如何使用匿名内部类?

Java中如何使用匿名内部类?,java,anonymous-class,anonymous-inner-class,Java,Anonymous Class,Anonymous Inner Class,Java中匿名类的用途是什么?我们可以说使用匿名类是Java的优点之一吗?您可以在需要在另一个函数中为特定目的创建类的情况下使用它,例如,作为侦听器,作为可运行的(生成线程)等 其思想是从函数的代码内部调用它们,这样就不会在其他地方引用它们,所以不需要命名它们。编译器只是枚举它们 它们本质上是合成糖,当它们变大时,通常应该移到别处 我不确定这是否是Java的优点之一,但如果你确实使用它们(不幸的是,我们都经常使用它们),那么你可以说它们是一个优点。我认为你的意思是“匿名类” 匿名内部类在生成具有

Java中匿名类的用途是什么?我们可以说使用匿名类是Java的优点之一吗?

您可以在需要在另一个函数中为特定目的创建类的情况下使用它,例如,作为侦听器,作为可运行的(生成线程)等

其思想是从函数的代码内部调用它们,这样就不会在其他地方引用它们,所以不需要命名它们。编译器只是枚举它们

它们本质上是合成糖,当它们变大时,通常应该移到别处

我不确定这是否是Java的优点之一,但如果你确实使用它们(不幸的是,我们都经常使用它们),那么你可以说它们是一个优点。

我认为你的意思是“匿名类”

匿名内部类在生成具有某些“附加”的对象实例(如重写方法)时非常有用,而不必实际对类进行子类化

我倾向于将其用作附加事件侦听器的快捷方式:

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // do something
    }
});
使用此方法可以加快编码速度,因为我不需要创建额外的类来实现
ActionListener
——我只需实例化一个匿名内部类,而不需要创建单独的类


我只在“快速而肮脏”的任务中使用这种技术,因为这样做会让整个类感觉不必要。如果有多个匿名内部类执行完全相同的操作,则应将其重构为实际的类,无论是内部类还是单独的类。

它们通常用作详细的回调形式

我想您可以说,与没有它们相比,它们是一个优势,并且每次都必须创建一个命名类,但是类似的概念在其他语言中实现得更好(如闭包或块)

下面是一个swing示例

myButton.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        // do stuff here...
    }
});

尽管它仍然杂乱无章,但它比像这样强迫您为每个一次性侦听器定义一个命名类要好得多(尽管取决于情况和重用,这可能仍然是更好的方法)

是的,匿名内部类肯定是Java的优势之一

使用匿名内部类,您可以访问周围类的final和member变量,这在侦听器中非常方便


但一个主要优点是,内部类代码(至少应该)与周围的类/方法/块紧密耦合,具有特定的上下文(周围的类、方法和块)。

匿名内部类实际上是闭包,因此它们可以用来模拟lambda表达式或“委托”。例如,以该接口为例:

public interface F<A, B> {
   B f(A a);
}
Java中的公共接口F。假设您有以下方法,该方法返回给定列表中大于i的第一个数字,如果没有大于i的数字,则返回i:

public static int larger(final List<Integer> ns, final int i) {
  for (Integer n : ns)
     if (n > i)
        return n;
  return i;
}
公共静态整数较大(最终列表ns,最终整数i){
for(整数n:ns)
如果(n>i)
返回n;
返回i;
}
还有另一个方法,它返回给定列表中小于i的第一个数字,如果没有小于i的数字,则返回i:

public static int smaller(final List<Integer> ns, final int i) {
   for (Integer n : ns)
      if (n < i)
         return n;
   return i;
}
公共静态整数较小(最终列表ns,最终整数i){
for(整数n:ns)
if(n
这些方法几乎相同。使用第一类函数类型F,我们可以将其重写为一个方法,如下所示:

public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
   for (T t : ts)
      if (f.f(t))
         return t;
   return z;
}
publicstatict firstMatch(最终列表ts、最终F、tz){
for(T:ts)
如果(f.f(t))
返回t;
返回z;
}
您可以使用匿名类来使用firstMatch方法:

F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
   Boolean f(final Integer n) {
      return n > 10;
   }
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
F greaterThanTen=新F{
布尔f(最终整数n){
返回n>10;
}
};
int大于MyFingerScanCount=第一个匹配项(xs,大于十,x);
这是一个非常做作的例子,但很容易看出,能够像传递值一样传递函数是一个非常有用的特性。乔尔亲自看


这是一个很好的Java编程库:

我有时使用它们作为映射实例化的语法黑客:

Map map = new HashMap() {{
   put("key", "value");
}};
vs


在执行大量put语句时,它可以节省一些冗余。但是,当外部类需要通过远程处理进行序列化时,我在执行此操作时也遇到了问题

匿名类指南

  • 同时声明和初始化匿名类

  • 匿名类必须扩展或实现一个且仅一个类或接口响应

  • 由于匿名类没有名称,因此只能使用一次

  • 例如:


    匿名类在类终结中的主要用法之一,称为终结器守护者。在Java世界中,应该避免使用finalize方法,直到您真正需要它们为止。您必须记住,当您重写子类的finalize方法时,您也应该始终调用
    super.finalize()
    ,因为super类的finalize方法不会自动调用,并且您可能会遇到内存泄漏问题

    因此,考虑到上述事实,您可以使用匿名类,如:

    public class HeavyClass{
        private final Object finalizerGuardian = new Object() {
            @Override
            protected void finalize() throws Throwable{
                //Finalize outer HeavyClass object
            }
        };
    }
    
    使用此技术,您可以让自己和其他开发人员轻松地对需要finalize方法的
    HeavyClass
    的每个子类调用
    super.finalize()

    new Thread() {
            public void run() {
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    System.out.println("Exception message: " + e.getMessage());
                    System.out.println("Exception cause: " + e.getCause());
                }
            }
        }.start();
    

    这也是使用线程的匿名内部类型的示例之一。我使用匿名对象调用新线程

    new Thread(new Runnable() {
        public void run() {
            // you code
        }
    }).start();
    

    匿名内部类在为不同的对象提供不同的实现时是有益的。但是应该非常谨慎地使用,因为它会给程序的可读性带来问题。

    在以下场景中使用匿名内部类:

    1.)对于重写(子类化),当类定义除当前情况外不可用时:

    class A{
        public void methodA() {
            System.out.println("methodA");
        }
    }
    
    class B{
        A a = new A() {
            public void methodA() {
                System.out.println("anonymous methodA");
            }
        };
    }
    
    interface InterfaceA{
        public void methodA();
    }
    
    class B{
        InterfaceA a = new InterfaceA() {
            public void methodA() {
                System.out.println("anonymous methodA implementer");
            }
        };
    }
    
    2.)对于实现接口,当仅在当前情况下需要实现接口时:

    class A{
        public void methodA() {
            System.out.println("methodA");
        }
    }
    
    class B{
        A a = new A() {
            public void methodA() {
                System.out.println("anonymous methodA");
            }
        };
    }
    
    interface InterfaceA{
        public void methodA();
    }
    
    class B{
        InterfaceA a = new InterfaceA() {
            public void methodA() {
                System.out.println("anonymous methodA implementer");
            }
        };
    }
    
    3.)中定义的匿名参数
    interface Foo {
        void methodFoo();
    }
    
    class B{
        void do(Foo f) { }
    }
    
    class A{
        void methodA() {
            B b = new B();
            b.do(new Foo() {
                public void methodFoo() {
                    System.out.println("methodFoo");
                } 
            });
        } 
    } 
    
    TreeSet treeSetObj = new TreeSet(new Comparator()
    {
        public int compare(String i1,String i2)
        {
            return i2.compareTo(i1);
        }
    });
    
    TypeHolder<List<String>, Map<Ineger, Long>> holder = 
        new TypeHolder<List<String>, Map<Ineger, Long>>() {};
    
    public class Person {
    
        public enum Sex {
            MALE, FEMALE
        }
    
        String name;
        LocalDate birthday;
        Sex gender;
        String emailAddress;
    
        public int getAge() {
            // ...
        }
    
        public void printPerson() {
            // ...
        }
    }
    
    public static void printPersons(
        List<Person> roster, CheckPerson tester) {
        for (Person p : roster) {
            if (tester.test(p)) {
                p.printPerson();
            }
        }
    }
    
    interface CheckPerson {
        boolean test(Person p);
    }
    
    printPersons(
        roster,
        new CheckPerson() {
            public boolean test(Person p) {
                return p.getGender() == Person.Sex.MALE
                    && p.getAge() >= 18
                    && p.getAge() <= 25;
            }
        }
    );
    
    printPersons(
                    roster,
                    (Person p) -> p.getGender() == Person.Sex.MALE
                            && p.getAge() >= 18
                            && p.getAge() <= 25
            );
    
    import java.util.Scanner;
    abstract class AnonymousInner {
        abstract void sum();
    }
    
    class AnonymousInnerMain {
        public static void main(String []k){
            Scanner sn = new Scanner(System.in);
            System.out.println("Enter two vlaues");
                int a= Integer.parseInt(sn.nextLine());
                int b= Integer.parseInt(sn.nextLine()); 
            AnonymousInner ac = new AnonymousInner(){
                void sum(){
                    int c= a+b;
                    System.out.println("Sum of two number is: "+c);
                }
            };
            ac.sum();
        }
    
    }
    
    ThreadClass task = new ThreadClass();
    Thread runner = new Thread(task);
    runner.start();
    
    Thread runner = new Thread(new Runnable() {
        public void run() {
            //Thread does it's work here
        }
    });
    runner.start();