小议局部类 (内部类, Inner Class)

简介:

假如你有一个 Integer 对象的列表,并且你想使用 Coolections.sort 来对它们进行排序。另外,你还要自己指定一个比较器,因为你想按降序而不是升序排列它们。这里有一些代码示例说明了该怎么做:

 
  1. import java.util.*;  
  2.  
  3. public class LocalDemo1 ...{  
  4.  
  5.     // 使用实现了 Comparator 的匿名类排序。  
  6.  
  7.     static void sortanon(List list) ...{  
  8.         Collections.sort(list, new Comparator() ...{  
  9.             public int compare(  
  10.                Object o1, Object o2) ...{  
  11.                  int cc = ((Integer)o1).compareTo(o2);  
  12.                  return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  13.             }  
  14.         });  
  15.     }  
  16.  
  17.     //  使用实现了 Comparator 的局部类排序  
  18.  
  19.     static void sortlocal(List list) ...{  
  20.         class MyComparator implements Comparator ...{  
  21.             public int compare(  
  22.                Object o1, Object o2) ...{  
  23.                  int cc = ((Integer)o1).compareTo(o2);  
  24.                  return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  25.             }  
  26.         };  
  27.  
  28.         Collections.sort(list, new MyComparator());  
  29.     }  
  30.  
  31.     public static void main(String[] args) ...{  
  32.         List list1 = new ArrayList();  
  33.         list1.add(new Integer(1));  
  34.         list1.add(new Integer(2));  
  35.         list1.add(new Integer(3));  
  36.         sortanon(list1);  
  37.         System.out.println(list1);  
  38.  
  39.         List list2 = new ArrayList();  
  40.         list2.add(new Integer(1));  
  41.         list2.add(new Integer(2));  
  42.         list2.add(new Integer(3));  
  43.         sortlocal(list2);  
  44.         System.out.println(list2);  
  45.     }  

这段程序的输出如下:

[3, 2, 1]
[3, 2, 1]

上列中使用两种不同的方法实现了 Comparator 接口。第一种方法使用匿名类,第二种方法使用局部类,二者有何区别:

一点区别是格式上的——匿名类的定义比较简捷,它实际上是下面这个表达式的一部分:

Comparator c = new Comparator() {...};

与之相反,局部类的定义看起来非常类似于常规的类定义,略为烦琐。例如,定义局部类内时可能用到 “implements”语句,而在匿名类中不需要显示的使用这条语句。

哪一种格式“更好”取决于你自己的观点。匿名类的定义会比较难读,但在不需要使用局部类的地方使用局部类会造成一些错觉,让人觉得需要做的事比实际要做的事更多。

让我们来看看另一个例子,更深层的比较匿名类和局部类:

 
  1. import java.util.*;  
  2.  
  3. public class LocalDemo2 ...{  
  4.  
  5.     // 使用两个单独的匿名类实例对两个列表进行排序  
  6.  
  7.     static void sort1(List list1, List list2) ...{  
  8.         Collections.sort(list1, new Comparator() ...{  
  9.             public int compare(  
  10.               Object o1, Object o2) ...{  
  11.                 int cc = ((Integer)o1).compareTo(o2);  
  12.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  13.             }  
  14.         });  
  15.  
  16.         Collections.sort(list2, new Comparator() ...{  
  17.             public int compare(  
  18.               Object o1, Object o2) ...{  
  19.                 int cc = ((Integer)o1).compareTo(o2);  
  20.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  21.             }  
  22.         });  
  23.     }  
  24.  
  25.     // 使用一个局部类的两个实例来对两个列表进行排序  
  26.  
  27.     static void sort2(List list1, List list2) ...{  
  28.         class MyComparator implements Comparator ...{  
  29.             public int compare(  
  30.               Object o1, Object o2) ...{  
  31.                 int cc = ((Integer)o1).compareTo(o2);  
  32.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  33.             }  
  34.         }  
  35.  
  36.         Collections.sort(list1, new MyComparator());  
  37.         Collections.sort(list2, new MyComparator());  
  38.     }  
  39.  
  40.     // 使用一个匿名类的一个实例来对两个列表进行排序   
  41.  
  42.     static void sort3(List list1, List list2) ...{  
  43.         Comparator cmp = new Comparator() ...{  
  44.             public int compare(  
  45.               Object o1, Object o2) ...{  
  46.                 int cc = ((Integer)o1).compareTo(o2);  
  47.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  48.             }  
  49.         };  
  50.  
  51.         Collections.sort(list1, cmp);  
  52.         Collections.sort(list2, cmp);  
  53.     }  
  54.  
  55.     // 使用一个局部类的一个实例来对两个列表进行排序  
  56.  
  57.     static void sort4(List list1, List list2) ...{  
  58.         class MyComparator implements Comparator ...{  
  59.             public int compare(  
  60.               Object o1, Object o2) ...{  
  61.                 int cc = ((Integer)o1).compareTo(o2);  
  62.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  63.             }  
  64.         }  
  65.  
  66.         Comparator cmp = new MyComparator();  
  67.  
  68.         Collections.sort(list1, cmp);  
  69.         Collections.sort(list2, cmp);  
  70.     }  
  71.  
  72.     static class AppComparator implements   
  73.      Comparator ...{  
  74.         public int compare(Object o1, Object o2) ...{  
  75.             int cc = ((Integer)o1).compareTo(o2);  
  76.             return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  77.         }  
  78.     }  
  79.  
  80.     static Comparator appcomparator =   
  81.        new AppComparator();  
  82.  
  83.     // 使用应用程序中定义的比较器来对两个列表进行排序  
  84.  
  85.     static void sort5(List list1, List list2) ...{  
  86.         Collections.sort(list1, appcomparator);  
  87.         Collections.sort(list2, appcomparator);  
  88.     }  
  89.  
  90.     public static void main(String[] args) ...{  
  91.         List list1 = new ArrayList();  
  92.         list1.add(new Integer(1));  
  93.         list1.add(new Integer(2));  
  94.         list1.add(new Integer(3));  
  95.  
  96.         List list2 = new ArrayList();  
  97.         list2.add(new Integer(4));  
  98.         list2.add(new Integer(5));  
  99.         list2.add(new Integer(6));  
  100.  
  101.         //sort1(list1, list2);  
  102.         //sort2(list1, list2);  
  103.         //sort3(list1, list2);  
  104.         //sort4(list1, list2);  
  105.         sort5(list1, list2);  
  106.  
  107.         System.out.println(list1);  
  108.         System.out.println(list2);  
  109.     }  

输出结果是:

[3, 2, 1]
[6, 5, 4]

程序中所有这些排序的方法都做同样的事情——降序排序两个列表中的 Integer 对象。

sort1 使用两个匿名类,每个都实现了 Comparator 接口。这两个类是相对独立的,但在逻辑上是重复的 (这样的代码非常糟糕)。

sort2 方法使用了一个局部类的两个实例。这是比 sort1 更好的方法,但这并不是最有效率的。

sort3 和 sort4 方法分均是使用的一个类的一个实例,它们在逻辑上也没有重复,所以是比较有效率的代码。这两段代码也有不同之处:sort3 比 sort4 更简捷,但 sort4 更具可读性。除了可读性,在这种情况下使用局部类没有更多的意义。

如果你需要在一个应用程序中使用同一种排序的策略,那么上述的四种方法都不是完全正确的。这种情况下,最好使用一个全局类或者内部类 (MyComparator),或者创建一个单独的可用于应用程序中任何地方的比较器实例。sort5 就是这种情况下的例子。

关于匿名类的另一个问题是它们必须基于一个已经存在的类或者接口创建,例如,你使用下面这句代码的时候:

Comparator c = new Comparator() {...};

实际上发生的事情是:从一个没有名字的类创建了实例,而这个类实现了 Comparator 接口。而对于局部类则没有这种限制。

匿名类和局部类更深层次的区别在于:匿名类不能定义构造器,因为它是没有名字的。不过它还是可以通过 {...} 格式的初始化代码块做一些简单的初始化,例如:

 
  1. import java.util.*;  
  2.  
  3. public class LocalDemo3 ...{  
  4.     public static void main(String[] args) ...{  
  5.         Comparator cmp1 = new Comparator() ...{  
  6.             ...{  
  7.                 System.out.println(  
  8.                    <object initialization>);  
  9.             }  
  10.  
  11.             public int compare(  
  12.               Object o1, Object o2) ...{  
  13.                 int cc = ((Integer)o1).compareTo(o2);  
  14.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  15.             };  
  16.         };  
  17.  
  18.         class MyComparator implements Comparator ...{  
  19.             public MyComparator(int x) ...{  
  20.                 System.out.println(  
  21.                    <constructor called> +  
  22.                    < with value > + x);  
  23.             }  
  24.  
  25.             public int compare(  
  26.               Object o1, Object o2) ...{  
  27.                 int cc = ((Integer)o1).compareTo(o2);  
  28.                 return (cc < 0 ? 1 : cc > 0 ? -1 : 0);  
  29.             };  
  30.         };  
  31.         Comparator cmp2 = new MyComparator(100);  
  32.     }  

这段程序将输出:

object initialization
constructor called with value 100

局部类可以拥有通过常规方法使用的构造器,而匿名类地必须通过 {...} 来实现初始化。

再次考虑关于对例表进行排序的例子。为局部类或内部类定义一个构造器,并通过传递参数的办法可以指定这个类的实例在操作过程中是按升序还是降序。在匿名类中要做到这一点则需要定义一个类成员级别的 final 变量。

在对类的主流应用中更适合使用局部类,因为你更熟悉。局部类也比匿名类更具可读性。同时,局部类的功能往往会超出你所需要的,那么这个时候,就更适合使用匿名类了。
 


本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/843241,如需转载请自行联系原作者

相关文章
|
6月前
|
Java
30、根据官方教程详解嵌套类、内部类、静态嵌套类、局部类、匿名类 ...
30、根据官方教程详解嵌套类、内部类、静态嵌套类、局部类、匿名类 ...
55 1
|
Java
5.1 内部类与外部类的关系:内部类的实例化方式
5.1 内部类与外部类的关系:内部类的实例化方式
209 0
|
设计模式 Java
3.2 内部类的类型:静态内部类
3.2 内部类的类型:静态内部类
70 0
|
Java 开发者
Class 类对象的三种实例化模式|学习笔记
快速学习 Class 类对象的三种实例化模式
174 0
Class 类对象的三种实例化模式|学习笔记
|
Java 编译器
第19篇:Java 中的 final 关键字、嵌套类、内部类、静态嵌套类、局部类
📝 有效 final:虽然没有被final修饰,但只进行了一次赋值(若被赋值了不止一次,则不是有效 final) 📝 从 Java8 开始,如果局部变量没有被第二次赋值,则该局部变量会被认定为是【有效 final】
132 0
第19篇:Java 中的 final 关键字、嵌套类、内部类、静态嵌套类、局部类
|
Java
第30篇:根据官方教程详解嵌套类、内部类、静态嵌套类、局部类、匿名类 ...
🌻 嵌套类、内部类、局部类等是 Java 面向对象中的难点,但好好研究清楚感觉也不是特别难。博主再次学习这部分内容,以次巩固知识。 🌻 博主其他介绍相关内容的文章:嵌套类、内部类、静态嵌套类... 🌻 博主以官方教程为基础开始学习,其中的概念都是以官方教程为主,这样学习起来比较放心。
153 0
第30篇:根据官方教程详解嵌套类、内部类、静态嵌套类、局部类、匿名类 ...
|
前端开发 JavaScript 开发者
class-使用 extends 实现子类继承父类|学习笔记
快速学习 class-使用 extends 实现子类继承父类
117 0
|
Java 开发者
Class 类对象的三种实例化模式|学习笔记
快速学习 Class 类对象的三种实例化模式
423 0
 Class  类对象的三种实例化模式|学习笔记
|
Java
java内部类深入详解 内部类的分类 特点 定义方式 使用
本文关键词: java内部类 内部类的分类 特点  定义方式 使用   外部类调用内部类 多层嵌套内部类  内部类访问外部类属性  接口中的内部类  内部类的继承  内部类的覆盖  局部内部类 成员内部类 静态内部类 匿名内部类 内部类定义 将一个类定义放到另一个类的内部,这就是内部类 ...
2739 0
|
Java
Java中,内部类的概述和内部类的访问特点和内部类的分类(内部类的位置)
内部类的概述:   把类定义在另一个类的内部,该类就被称为内部类。   举例:把类B定义在类A中,类B就被称为内部类。 内部类的访问特点:   A:内部类可以直接访问外部类的成员,包括私有成员。
1063 0