JAVA 复习(Think In Java, 4th) -- Inner Classes - Part1

内部类(Inner Class)

一个类是可以在其它类中定义的类,我们可以将数据储存在有意义的内部类,在别人调用我们类、运用相关方法的时候,能做更有序、灵活的运用,如下:

public class EasyInnerClass {
    private People list[] = null;
    private int count = 0;
    public EasyInnerClass() {
        list = new People[5];
    }
    class People {
        String name;
        int height;
        int weight; 
     
        public String toString() {
            return "[ "+name+" ]: height- "+height+" ,weight- "+weight; 
        }
    }

    public void enrollPeople(String name, int h, int w) {
        if(count < 5) {
            People theOne = new People();
            theOne.name = name;
            theOne.height = h;
            theOne.weight = w;
            list[count] = theOne; 
            count++;
        } else {
            System.out.println("too many people...");    
        }
    }    

    public void printList() {
        if(list.length > 0)
            for(int i = 0; i < list.length; i++)
            {
                if(list[i]!=null)
                    System.out.println(list[i].toString()); 
            }
        else
            System.out.println("no one is on the list");
    }

    public static void main(String[] args) {
        EasyInnerClass ec = new EasyInnerClass();
        ec.enrollPeople("jg",150,60);
        ec.enrollPeople("zg",150,60);
        ec.enrollPeople("st",150,60);
        ec.enrollPeople("ot",150,60);
        ec.enrollPeople("dt",150,60);
        ec.enrollPeople("sd",150,60);

        ec.printList();
    }
}

比如在上例,我们在 enrollPeople() 这个方法中,产生一个用内部类对象构建的对象,数据存到该对象,并将这个对象存在一个数组中,而调用此 API的人,便无须了解我们如何処理这些数据,只要有合理的输入及正确的输出即可。另外要注意的是,当自外部宣告非静态( non-static )内部类时,应为:

外部类名.内部类名   变数名 = 外部类变数.宣告方法()
如下:
public class EasyInnerClass {
    public class People {
        String name;
        int height;
        int weight; 

        public People(String n, int h, int w) {
            name = n;
            height = h;
            weight = w;
        }

        public String toString() {
            return "[ "+name+" ]: height- "+height+" ,weight- "+weight; 
        }
    }

    public People initPeople(String name, int h, int w){
        return new People(name,h,w);
    }

    public void printPeople(People ppl) {
        System.out.println(ppl.toString());
    }
 
    public static void main(String[] args) {
        EasyInnerClass ec = new EasyInnerClass();
        EasyInnerClass.People one = ec.initPeople("John",175,65);
        ec.printPeople(one);
    }
}

如果用下面的方法这麽写:

    public static void main(String[] args) {
        EasyInnerClass ec = new EasyInnerClass();
        EasyInnerClass.People one = new EasyInnerClass.People("john",149,22); 
        ec.printPeople(one);
    }


"non-static variable this cannot be referenced from a static context" 这句话的意思是说 EasyInnerClass.People 是一个静态的上下文(static context),而 new 是一个非静态的变数宣告方法,此処所宣告的内存为动态内存,不能为静态上下文所引用。(因为静态变数在内存中的位置是一开始就知道的,而动态变数是程序执行中才会知道的)修改的办法除了上面的方法以外,我们也可以将内部类改为静态的内部类,如下:

public class EasyInnerClass {
    public static class People {
        String name;
        int height;
        int weight; 

        public People(String n, int h, int w) {
            name = n;
            height = h;
            weight = w;
        }

        public String toString() {
            return "[ "+name+" ]: height- "+height+" ,weight- "+weight; 
        }
    }

    public People initPeople(String name, int h, int w){
        return new People(name,h,w);
    }

    public void printPeople(People ppl) {
        System.out.println(ppl.toString());
    }
 
    public static void main(String[] args) {
        EasyInnerClass ec = new EasyInnerClass();
        People one = new People("john",149,22); 
        ec.printPeople(one);
    }
}


在下面这个范例中,内部类作为判断目前数组 index 的方法,它可以存取 private 属性的 ObArray 以判断和实现 InnerPointer 接口,如下:

public class InnerArray {
    private Object[] ObArray;
    private int next;

    interface InnerPointer {
        boolean end();
        void next();
        Object current();
    }

    private class InnerPointerImpl implements InnerPointer {
        private int i = 0;
        @Override
        public boolean end() {
            return i == ObArray.length;    
        }
 
        @Override
        public void next() {
            if(!end())
                i++;
            else
                System.out.println("Out of index");
        }

        @Override
        public Object current() {
            return ObArray[i];
        }    
    }

    public InnerArray(int size) {
        ObArray = new Object[size];
    }
    
    public InnerPointerImpl initInnerPointerImpl() {
        return new InnerPointerImpl();
    }
    
    public void add(Object a) {
        if(next < ObArray.length) {
            ObArray[next] = a;
            next++;
        }
        else
            System.out.println("out of array index");
    }

    public static void main(String[] args) {
        InnerArray ia = new InnerArray(10);
        InnerArray.InnerPointerImpl ip = ia.initInnerPointerImpl();
        for(int i = 0; i < 10; i++)
        {
            ia.add(i); 
        }

        while(!ip.end())
        {
            System.out.println(String.valueOf(ip.current()));
            ip.next();
        }
    }
}


.this 和 .new

类名.this
可以很方便的让我们在内部类里指向外面类的对象,而有时我们需要用外部类去宣告它的内部类,这时我们便可以用

外部类对象.new 内部类名();

如下:

import java.util.Arrays;
public class DotNewPractice {
    private Object[] jobQueue;
    private int curExecIndex;
    private interface ProgressListener {
        float getCurrentProgress();
        boolean isEnd();
    }

    private ProgressListener listener;

    public DotNewPractice(int jobNum) {
        System.out.println("this is: " + this.getClass());
        jobQueue = new Object[jobNum];
    }

    public void execute() {
        final int Len = jobQueue.length;
        for(int i =0; i<Len; i++) {
            jobQueue[i] = 0;
            curExecIndex = i;
            System.out.println(""+listener.getCurrentProgress()+"%");
        }
    }

    public void getJobs() {
        Arrays.fill(jobQueue,100);
    }

    public void initListener() {
        listener = new innerclass();
    }

    public void setProgressListener(ProgressListener ltn) {
        listener = ltn;
    }

    public class innerclass implements ProgressListener {
        public innerclass() {
            System.out.println("this is: " + this.getClass());
            System.out.println("Outer Class this is: " + DotNewPractice.this.getClass()); // 外部类名.this 在这~
            System.out.println(innerclass.this.getClass() + " created!"); 
        }
        
        @Override
        public float getCurrentProgress() {
             return ((float)(curExecIndex+1)/(float)jobQueue.length)*100;
        }

        @Override
        public boolean isEnd() {
             return (curExecIndex+1 == jobQueue.length);
        }   
    };

    public static void main(String[] args) {
        DotNewPractice dp = new DotNewPractice(10);
        dp.setProgressListener(dp.new innerclass()); // 用dp.initListener(); 也会得到一样的效果
        dp.getJobs();
        dp.execute();
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值