`
nwenji
  • 浏览: 14576 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

嵌套类和匿名类

 
阅读更多

原文:http://blog.163.com/c_123xyz/blog/static/7709247620087323051182/

 

 

内部类的出现
当进行Java开发时,有时需要实现一个仅包含1-2个方法的接口.在AWT和Swing开发中经常出现这种情况,例如当一个display组件需要一个 事件回调方法如一个按钮的ActionListener时. 如果使用普通的类来实现此操作,最终会得到很多仅在单个位置上使用的小型类. 
内部类用于处理这种情况,java允许定义内部类,而且可在Gui外使用内部类.

内部类的定义和实现

内部类是指在另一个类内部定义的一个类.可以将内部类定义为一个类的成员.
public class Linker{
  public class LinkedNode{
    private LinkedNode prev;
    private LinkedNode next;
    private String content;
    
    public LinkedNode(String content){
      this.content=content;
    }
  }
  
  public Linker(){
    LinkedNode first=new LinkedNode("First");
    LinkedNode second=new LinkedNode("Second");
    
    first.next=second;
    second.prev=first;
  }
}

定义在一个类方法中的内部类

public class Hapiness{
  interface Smiler{
    public void smile();
  }
  
  public static void main(String[] args){
    class Happy implements Smiler{
      public void smile(){
        System.out.println(":-}");
      }
    }
    
    Happy happy=new Happy();
    happy.smile();
  }
}

匿名类

对很多情况而言,定义在方法内部的类名意义不大,它可以保持为匿名的,程序员关心的只是它的实例名.
如:
Runnable runner=new Runnable(){
     public void  run(){
          // Run statememnt
     }
}

理解匿名类

匿名类并不难理解,它只是把类的定义过程和实例的创建过程混合而已,上页的语句实际上相当于如下语句:
// 定义类
Public class Runner implements Runnable{
     public void run(){
         // do sth
      }
}

// 创建实例
Runner runner=new Runner();

使用匿名类的筛选解耦过程

需求:从公司的职员列表中,找出男性且年龄大于22的成员.

传统写法:

   List allmembers=company.getMembers();// 取得所有成员
    List results=new ArrayList();// 结果列表
    
    for(Iterator it=allmembers.iterator();it.hasNext();){
     Member member=(Member)it.next();
     
     if(member.getAge()>22 && member.isMale()){  // 筛选,这里是把查询条件和遴选过程融合在一起,条件一变立即就得加个分支.
      results.add(member);
     }
   }

传统方法的缺陷

这种写法没有错,但是不是面向对象的写法,它有以下缺陷:
1.查询条件和筛选过程没有分离.
2.这样写的后果使Company变成了一个失血模型而不是领域模型.
3.换查询条件的话,上面除了"筛选"一句有变化外其它都是模板代码,重复性很高.

使用匿名类实现的OO化查询

真正符合OO的查询应该是这样:

   MemberFilter filter1=new MemberFilter(){
    public boolean accept(Member member) {
         return member.isMale() && member.getAge()>22;
    }
   };
   
   List ls=company.listMembers(filter1);
 

这段代码成功的把查询条件作为一个接口分离了出去,接口代码如下:

public interface MemberFilter{
  public boolean accept(Member member); 
}

查询函数的变化

而类Company增加了这样一个函数:

public List searchMembers(MemberFilter memberFilter){
   List retval=new ArrayList();
    
    for(Iterator it=members.iterator();it.hasNext();){
     Member member=(Member)it.next();
     
     if(memberFilter.accept(member)){
      retval.add(member);
    }
   }  
   
   return retval;
}
这就把模板代码归结到了类内部,外面不会重复书写了.Company也同时拥有了数据和行为,而不是原来的数据容器了.


匿名类的例子二

用匿名类处理分类汇总的方法 分类汇总是统计中常用,举例来说如统计学生成绩,及格不及格的归类,分优良中差等级归类等,每个单项代码很好写,但是如果分类汇总的项目多了,能一种汇总 写一个函数吗? 比如说有些科目60分才算及格,有些科目50分就算;有些老师喜欢分优良中差四等,有些老师却喜欢分ABCD;不一而足,如果每个都写一个函数无疑是个编 写和维护恶梦. 如果我们用匿名类把分类汇总的规则和分类汇总的过程分别抽象出来,代码就清晰灵活多了,以下代码讲述了这个过程.

基本类Student

public class Student{
    private String name;
    private int score;
    
    public Student(String name,int score){
        this.name=name;
        this.score=score;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }    
}


用于分类汇总的类

它强制子类实现getKey和getvalue两个方法:
public abstract class ClassifyRule {
    public Student student;
    
    public ClassifyRule(){        
    }   

    public void setStudent(Student student) {
        this.student = student;
    }
    
    abstract public String getKey();
    abstract public int getValue();
}

对Student进行统计处理的StudentService类

注意getSum方法,它保留了筛选过程,筛选规则则不在其中:
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

public class StudentService {
    private List<Student> students;

    public StudentService() {
        students = new ArrayList<Student>();
    }

    public void add(Student student) {
        students.add(student);
    }

    public Hashtable<String, Integer> getSum(ClassifyRule rule) {
        Hashtable<String, Integer> ht = new Hashtable<String, Integer>();

        for (Student student : students) {
            rule.setStudent(student);
            String key = rule.getKey();
            int value = rule.getValue();

            if (ht.containsKey(key)) {
                Integer oldValue = ht.remove(key);
                oldValue += value;
                ht.put(key, oldValue);
            } else {
                ht.put(key, value);
            }
        }

        return ht;
    }
}

测试代码,注意其中筛选规则的创建

public class Test {
    public static void main(String[] args) {
        // 初始化
        StudentService service = new StudentService();
        service.add(new Student("Andy", 90));
        service.add(new Student("Bill", 95));
        service.add(new Student("Cindy", 70));
        service.add(new Student("Dural", 85));
        service.add(new Student("Edin", 60));
        service.add(new Student("Felix", 55));
        service.add(new Student("Green", 15));

        // 60分及格筛选
        ClassifyRule rule60 = new ClassifyRule() {
            public String getKey() {
                return student.getScore() >= 60 ? "及格" : "不及格";
            }

            public int getValue() {
                return 1;
            }
        };

        System.out.println("60分及格筛选");
        printHt(service.getSum(rule60));

        // 50分及格筛选
        ClassifyRule rule50 = new ClassifyRule() {
            public String getKey() {
                return student.getScore() >= 50 ? "及格" : "不及格";
            }

            public int getValue() {
                return 1;
            }
        };
        System.out.println("\n50分及格筛选");
        printHt(service.getSum(rule50));

        // 分"优良中差"等级
        ClassifyRule ruleCn = new ClassifyRule() {
            public String getKey() {
                String retval = "";

                int score = student.getScore();
                if (score >= 90) {
                    retval = "优";
                } else if (score >= 80) {
                    retval = "良";
                } else if (score >= 60) {
                    retval = "中";
                } else if (score > 0) {
                    retval = "差";
                }

                return retval;
            }

            public int getValue() {
                return 1;
            }
        };

测试代码

System.out.println("\n分优良中差等级筛选");
        printHt(service.getSum(ruleCn));

        // 分"ABCD"等级
        ClassifyRule ruleWest = new ClassifyRule() {
            public String getKey() {
                String retval = "";

                int score = student.getScore();
                if (score >= 90) {
                    retval = "A";
                } else if (score >= 80) {
                    retval = "B";
                } else if (score >= 60) {
                    retval = "C";
                } else if (score > 0) {
                    retval = "D";
                }

                return retval;
            }

            public int getValue() {
                return 1;
            }
        };

        System.out.println("\n分ABCD等级筛选");
        printHt(service.getSum(ruleWest));
    }

    private static void printHt(Hashtable ht) {
        for (Iterator it = ht.keySet().iterator(); it.hasNext();) {
            String key = (String) it.next();
            Integer value = (Integer) ht.get(key);
            System.out.println("Key=" + key + " Value=" + value);
        }
    }
}


测试结果如下:

 

60分及格筛选
Key=及格 Value=5
Key=不及格 Value=2

50分及格筛选
Key=及格 Value=6
Key=不及格 Value=1

分优良中差等级筛选
Key=优 Value=2
Key=良 Value=1
Key=中 Value=2
Key=差 Value=2

分ABCD等级筛选
Key=A Value=2
Key=D Value=2
Key=C Value=2
Key=B Value=1

后记

内部类也叫嵌套类,一般不提倡书写,但它在java核心类中都存在,如接口Map中的Entry,我们应该了解并能解读这种方法.

匿名类相对而言有用得多,在解耦合和事件回调注册中很常见,大家应该对它的运用融会贯通.
 
分享到:
评论

相关推荐

    Java 深入理解嵌套类和内部类

    非静态嵌套类可以分为三种:在一个类中直接定义的内部类、在一个方法中定义的内部类和匿名内部类。匿名内部类是指没有名字的内部类,通常用于实现某个接口或继承某个类。 四、在外部类中定义内部类 在外部类中定义...

    嵌套类内存布局分析(vc)

    3. **匿名嵌套类(Anonymous Nested Class)**:如果嵌套类没有名字,它会直接作为外部类的一部分,其成员可以直接作为外部类的成员使用。在这种情况下,嵌套类对象的内存通常会合并到外部类的内存布局中。 在VC中...

    java和kotlin的内部类静态嵌套类

    内部类分为四种类型:成员内部类、局部内部类、匿名内部类和静态嵌套类。其中,静态嵌套类是与外部类关联但不持有对外部类的引用,因此它可以像普通类一样被静态引用,而无需外部类实例。 Java的静态嵌套类通常用于...

    嵌套类的学习

    嵌套类,顾名思义,就是在类内部定义的另一个类,它可以是静态的,也可以是非静态的,根据其特性,可以分为内部类(Inner Class)和嵌套类(Nested Class)。在本文中,我们将深入探讨嵌套类的概念、分类、用法以及...

    java嵌套类

    首先,根据嵌套类定义的位置,可以将嵌套类分为成员嵌套类(Member Nested Classes)、局部嵌套类(Local Nested Classes)和匿名嵌套类(Anonymous Nested Classes)。 成员嵌套类是指作为外部类(Enclosing Class...

    java-嵌套类(inner class)-来自oracle官网

    嵌套类主要分为两大类:静态嵌套类(Static Nested Class)和非静态嵌套类(Non-static Nested Class),后者通常被称为内部类(Inner Class)。 - **静态嵌套类**:此类嵌套类被声明为`static`,因此它们与外部类...

    Java4Android 35_内部类和匿名内部类

    在Java编程语言中,内部类和匿名内部类是两种特殊类型的类,它们为代码的组织和功能实现提供了独特的灵活性。本教程"Java4Android 35_内部类和匿名内部类"深入探讨了这两个概念,旨在帮助开发者更好地理解和运用它们...

    深入理解Java嵌套类和内部类

    Java 嵌套类(nested classes)是指在一个类的内部定义另一个类,这种类有两种类型:静态嵌套类和非静态嵌套类。非静态嵌套类也称为内部类(inner classes)。在Java中,嵌套类从JDK1.1开始引入。 一、什么是嵌套类...

    Java中的内部类和匿名类

    Java 中的内部类和匿名类 Java 中的内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在 C++ 里也有,那就是嵌套类(Nested Class)。内部类从表面上看,就是在类中又定义了一个类,而实际上并没有那么...

    Java嵌套类和内部类详解

    Java中的嵌套类和内部类是面向对象编程中一种特殊的类定义方式,允许在一个类的定义内部创建另一个类。这种特性使得代码结构更加紧凑,同时也提供了更高级别的封装和抽象。在Java中,嵌套类分为静态嵌套类和非静态...

    java开发中嵌套类的详解及实例

    嵌套类可以分为三种类型:成员嵌套类、局部嵌套类和匿名嵌套类。 1. 成员嵌套类(Member Nested Class) 成员嵌套类是定义在外围类的成员变量中的类。成员嵌套类可以使用public、private、protected访问控制符,也...

    详解Java 中的嵌套类与内部类

    嵌套类有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类较少使用,非静态嵌套类使用较多,也就是常说的内部类。 静态嵌套类(Static Nested Class)是指在外部类中使用static关键字修饰的嵌套类。静态嵌套类可以...

    java基础讲课安排

    7. **内部类**:介绍嵌套类和匿名类的概念和应用场景。 8. **垃圾回收机制**:了解Java的自动内存管理机制。 9. **Javadoc**:学习如何生成和使用API文档。 **第三阶段:Java核心API与高级特性** 1. **Java API**:...

    内部类分类及应用

    内部类可以分为四种:成员内部类、静态嵌套类、方法内部类和匿名内部类。每种内部类都有其特点和应用场景。 一、成员内部类 成员内部类是指定义在外部类中的内部类。它们可以访问外部类的所有成员变量和方法,无论...

    匿名内部类_Anoymous_Inner_

    5. **内部类与嵌套类的区别**:内部类分为匿名内部类和非匿名内部类(如成员内部类和局部内部类)。非匿名内部类是具有名称的类,可以访问外部类的成员,包括私有成员。而匿名内部类没有名称,不能直接访问外部类的...

    内部类 匿名内部类 内部接口 对比说明

    本文将详细探讨内部类、匿名内部类以及内部接口的对比和使用。 首先,让我们了解一下内部类的基本概念。内部类定义在其他类的内部,编译后会生成两个独立的类文件。内部类能够自由地访问外部类的所有成员,包括私有...

    全面了解Java中的内部类和匿名类

    Java中的内部类和匿名类是Java语言的一个特色特性,它们为程序员提供了更加灵活和强大的代码组织方式。内部类,也称为嵌套类,可以分为两种类型:静态内部类和非静态内部类。非静态内部类与外部类之间存在紧密的关联...

    Java内部类和包装类.ppt

    放在另一个类的内部,这就是内部类(有的地方叫嵌套类), 包含内部类的类也被称为外部类(有的地方也叫宿主类) 匿名内部类就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 ...

    深入讲解C#编程中嵌套类型和匿名类型的定义与使用

    在C#编程中,嵌套类型和匿名类型是两种非常重要的概念,它们分别提供了不同的方式来组织和操作数据。下面将详细阐述这两种类型的定义、用途和使用方法。 **嵌套类型** 嵌套类型是在一个类或结构内部定义的类型,它...

    Java语法总结 - 内部类

    内部类可以分为四种:成员内部类、静态嵌套类、方法内部类和匿名内部类。 成员内部类 成员内部类是定义在外部类的成员变量中的一种内部类。它可以访问外部类的所有成员变量和方法,包括私有的变量和方法。成员内部...

Global site tag (gtag.js) - Google Analytics