`
nwenji
  • 浏览: 13920 次
  • 性别: 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嵌套类和内部类详解

    主要介绍了Java嵌套类和内部类详解,本文讲解了什么是嵌套类及内部类、静态嵌套类、在外部类中定义内部类、在方法中定义内部类、匿名内部类等内容,需要的朋友可以参考下

    Java内部类和包装类.ppt

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

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

    主要介绍了C#编程中嵌套类型和匿名类型的定义与使用,包括在SQL语句中使用匿名类型的方法,需要的朋友可以参考下

    数据库动态加载匿名对象

    5 匿名类型之间可嵌套 6 公有属性 可写 公有字段) 特性: 1 数据库字段与类属性或类字段按名称映射 2 数据库字段与类属性或类字段不区分大小写映射 3 始终按先区分大小写 未找到再不区分大小 仍未找到则...

    JAVA内嵌类代码.rar

    内嵌套类包括了静态类和成员类,还有方法中的类和匿名类的基本规则。

    JAVA语法总结 - 内部类

    内部类分为成员内部类、静态嵌套类、方法内部类、匿名内部类。 几种内部类的共性: A、内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。 B、内部类不能...

    几行代码带你彻底搞懂Java内部类

    内部类基本概述语法格式成员内部类局部内部类匿名内部类静态嵌套类静态嵌套类和非静态嵌套类的区别 内部类 基本概述 当一个类的定义放在另一个类的实体时,则该类叫做内部类,该类所在的类叫做外部类 在一个类体中...

    C#匿名委托和Java匿名局部内部类使用方法示例

    Java在嵌套类型这里提供的特性比较多,假设:Java的字节码只支持静态嵌套类,内部类、局部内部类和匿名局部内部类都是编译器提供的语法糖,这个假设目前没法验证(看不懂字节码),本文先来看一下C#是如何为我们提供...

    matlab匿名函数M文件函数嵌套函数子函数私有函数重载函数.pdf

    matlab匿名函数M文件函数嵌套函数子函数私有函数重载函数.pdf

    《Java和Android开发实战详解》第6到10章源代码-by 南邮-陈杨

    9.2.3 匿名内层类与this和final关键字 178 9.3 多态基础 180 9.3.1 静态绑定与动态绑定 180 9.3.2 Java语言支持的多态 181 9.4 多态的实现 181 9.4.1 使用类继承来实现多态 181 9.4.2 使用接口来实现...

    matlab匿名函数M文件函数嵌套函数子函数私有函数重载函数[归纳].pdf

    matlab匿名函数M文件函数嵌套函数子函数私有函数重载函数[归纳].pdf

    Java中的匿名内部类小结

    java内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。这篇文章主要介绍了Java中的匿名内部类的相关资料,需要的朋友可以参考下

    (超赞)JAVA精华之--深入JAVA API

    1.2 深入理解嵌套类和内部类 1.2.1 什么是嵌套类及内部类? 1.2.2 静态嵌套类 1.2.3 在外部类中定义内部类 1.2.4 在方法中定义内部类 1.2.5 匿名内部类 1.2.6 内部类使用的其它的问题 1.3 文件和流 1.3.1 什么是数据...

    ScrollView嵌套ListView滑动冲突的解决方法

    ScrollView嵌套ListView滑动冲突的解决方案

    JAVA SE学习精华集锦

    1.2 深入理解嵌套类和内部类 47 1.2.1 什么是嵌套类及内部类? 47 1.2.2 静态嵌套类 48 1.2.3 在外部类中定义内部类 48 1.2.4 在方法中定义内部类 49 1.2.5 匿名内部类 49 1.2.6 内部类使用的其它的问题 50 1.3 文件...

    Java内部类的一些总结

     内部类分为: 成员内部类、局部内部类、静态嵌套类、匿名内部类 。  1.成员内部类  成员内部类是普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:  class Outter {  private int age = 12;...

    JAVA精华.doc

    包含了J2SE 中大部分API的应用。嵌套类,匿名类, IO流,JMX规范 Log4J. Dom4j等

Global site tag (gtag.js) - Google Analytics