博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java笔记:内部类
阅读量:4953 次
发布时间:2019-06-12

本文共 7937 字,大约阅读时间需要 26 分钟。

1.把一个类放在另一类内部定义,这个定义在其他类里面的类就叫做内部类,包含内部类的类叫做外部类。内部类成员可以直接访问外部类的私有数据,但是外部类不能访问内部类的实现细节。

2.非静态内部类(没有static修饰的内部类)

package cn.lsl;public class Cow {    private double weight;    public Cow(){}    public Cow(double weight){        this.weight = weight;    }        private class CowLeg{        private double length;        private String color;        public CowLeg(double length, String color) {            super();            this.length = length;            this.color = color;        }        public double getLength() {            return length;        }        public void setLength(double length) {            this.length = length;        }        public String getColor() {            return color;        }        public void setColor(String color) {            this.color = color;        }        public void info(){            System.out.println("颜色:" + color + ",高:" + length);            System.out.println("重:" + weight);        }    }        public void test(){        CowLeg cl = new CowLeg(2, "红色");        cl.info();    }        public static void main(String[] args) {        Cow cow = new Cow(123);        cow.test();    }}

System.out.println("重:" + weight);这句代码在非静态内部类里可以直接访问外部类的private成员。

当调用非静态内部类的实例方法时,必须有一个静态内部类实例,而非静态内部类实例必须寄存在外部类实例里。

3.如果在外部类、内部类、内部类里方法里面出现了同名的变量,则可以通过this、外部类类名.this来访问

package cn.lsl;public class Variable {    private String a = "外部类实例变量";    private class In{        private String a = "内部类实例变量";        public void info(){            String a = "局部变量";            System.out.println("外部类:" + Variable.this.a);            System.out.println("内部类:" + this.a);            System.out.println("局部变量:" + a);        }    }    public void test(){        In in = new In();        in.info();    }        public static void main(String[] args) {        new Variable().test();    }}

三种访问形式:

System.out.println("外部类:" + Variable.this.a);
System.out.println("内部类:" + this.a);
System.out.println("局部变量:" + a);

4.外部类不能直接访问非静态内部类的实例Field,如果外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问其实例成员。

package cn.lsl;public class Outer {    private int a = 5;    class In{        private int b = 23;        public void accessOuter(){            System.out.println("直接访问外部类的a的值" + a);        }    }        public void accessIn(){        //System.out.println("内部类b的值:" + b);  编译出错,不能直接访问        System.out.println("内部类b的值:" + new In().b);    }            public static void main(String[] args) {        Outer out = new Outer();        out.accessIn();    }}

非静态内部类对象必须寄存在外部类对象里面,而外部类对象不一定要有非静态内部类对象寄存其中。即,如果存在一个非静态内部类对象,一定要存在一个被它寄存的外部类对象。

5.静态内部类(使用static修饰的内部类)
(1)如果使用static修饰一个内部类,则这个内部类就属于外部类本身,不属于外部类的某个对象。
(2)静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。

package cn.lsl;public class StaticIn{    private int a = 5;    private static int b = 23;    static class In{        private static int age;        public void accessOut(){            //System.out.println(a);        //编译出错            System.out.println(b);        }    }}

(3)外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员

package cn.lsl;public class StaticIn{        static class In{        private static int a = 5;        private int b = 23;    }        public void accessIn(){//        System.out.println(a);        //编译出错        System.out.println(In.a);//        System.out.println(b);        //编译出错        System.out.println(new In().b);    }}

6.在外部类以外使用非静态内部类

如果希望在外部类以外的地方访问内部类,则内部类不能使用private访问控制权限,private修饰的内部类只能在外部类内部使用。
非静态内部类的对象必须寄存在外部类的对象里,因此创建非静态内部类之前,必须先创建其外部类对象。

eg:package cn.lsl;class Out {    class In{        public In(String msg){            System.out.println(msg);        }    }} public class CreateIn{     public static void main(String[] args) {        Out.In in = new Out().new In("测试信息");    } }

在外部类以外的地方创建非静态内部类实例必须使用外部类实例和new来调用非静态内部类的构造器。

7.在外部类以外使用静态内部类
因为静态内部类是外部类类相关的,因此创建内部类对象时无须创建外部类对象。

package cn.lsl;class StaticOut{    static class In{        public In(){            System.out.println("静态内部类的构造器");        }    }}public class CreateStaticOut {    public static void main(String[] args) {        StaticOut.In in = new StaticOut.In();    }}

静态内部类和非静态内部类声明变量的语法是一样的,区别在于创建内部类对象时,静态内部类只需使用外部类即可调用构造器,而非静态内部类必须使用外部类对象来调用构造器。

8.局部内部类

如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。
由于局部内部类不能再方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。
如果需要用局部内部类定义变量,创建实例或派生子类,那么都只能在局部内部类所在的方法内进行。

package cn.lsl;public class LocalIn {    public static void main(String[] args) {        class InnerBase{            int a;        }        class InnerSub extends InnerBase{            int b;        }        InnerSub is = new InnerSub();        is.a = 5;        is.b = 8;        System.out.println(is.a + "," + is.b);    }}

9.匿名内部类

(1)匿名内部类适合创建那种只需要一次使用的类,创建匿名内部类时会立即创建一个该类的实例,这个类定义即消失,匿名内部类不能重复使用。
(2)匿名内部类的格式

new 父类构造器(实参列表)|实现接口(){}

(3)匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类,或实现一个接口。

(4)匿名内部类不能是抽象类。
(5)匿名内部类不能定义构造器,因为匿名内部类没有类名,所以无法定义构造器。但匿名内部类可以定义实例初始化块,通过实例初始化块来完成构造器需要完成的事情。

 

package cn.it.lsl;interface Product{    public double getPrice();    public String getName();}public class AnonymousTest{    public void test(Product p){        System.out.println("购买" + p.getName() + ",花掉了" + p.getPrice());    }    public static void main(String[] args) {        AnonymousTest ta = new AnonymousTest();        ta.test(new Product(){            @Override            public double getPrice() {                // TODO Auto-generated method stub                return 190;            }            @Override            public String getName() {                // TODO Auto-generated method stub                return "声卡";            }                });    }}

 

test()方法需要传入一个Product对象作为参数,但Product只是一个接口,因此此处考虑创建一个Product接口实现类的对象传入该方法。

上面匿名内部类部分也可以等价于下面这段代码

public class AnonymousTest implements Product{    @Override    public double getPrice() {        // TODO Auto-generated method stub        return 100;    }    @Override    public String getName() {        // TODO Auto-generated method stub        return "声卡";    }        public void test(Product p){        System.out.println("购买" + p.getName() + ",花掉了" + p.getPrice());    }        public static void main(String[] args) {        AnonymousTest ta = new AnonymousTest();        ta.test(new AnonymousTest());    }}

10.如果通过继承父类来创建匿名内部类,匿名内部类将拥有和父类相似的构造器,此处的相似指的是拥有相同的形参列表。

package cn.it.lsl;abstract class Device{    private String name;    public abstract double getPrice();    public Device(){}    public Device(String name){        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}public class AnonymousInner {    public void test(Device d){        System.out.println("购买一个" + d.getName() + ",花掉了" + d.getPrice());    }        public static void main(String[] args) {        AnonymousInner ai = new AnonymousInner();        ai.test(new Device("鼠标"){            @Override            public double getPrice() {                // TODO Auto-generated method stub                return 23;            }        });        Device d = new Device() {            {                System.out.println("匿名内部类初始化块");            }                        @Override            public double getPrice() {                // TODO Auto-generated method stub                return 32;            }                        //重写父类的实例方法            public String getName(){                return "键盘";            }        };        ai.test(d);    }}

当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法。如果有需要,也可以重写父类中的普通方法。

11.如果匿名内部类需要访问外部类的局部变量,则必须使用final修饰符来修饰外部类的局部变量

package cn.it.lsl;interface A{    void test();}public class ATest {    public static void main(String[] args) {        //int age = 0;        final int age = 0;        A a = new A(){            @Override            public void test() {                System.out.println(age);                            }                    };    }}

 

 

转载于:https://www.cnblogs.com/EvanLiu/p/3141127.html

你可能感兴趣的文章
linux下查看系统信息
查看>>
初识springcloud (一)
查看>>
浅谈布隆过滤器Bloom Filter
查看>>
Ember——路由处理器
查看>>
SUOI #2 someGCD
查看>>
编程里的单一职责
查看>>
python 之 列表与字典
查看>>
课后作业-阅读任务-阅读提问-1
查看>>
使用第三方jar时出现的问题
查看>>
Oracle临时表GLOBAL TEMPORARY TABLE
查看>>
SQL Server 获取日期时间并格式化
查看>>
上传文件中文文件名乱码的解决方法以及iconv函数的使用
查看>>
NSDictionary
查看>>
【原】iOS中KVC和KVO的区别
查看>>
OMAPL138学习----DSPLINK DEMO解析之SCALE
查看>>
IoC的基本概念
查看>>
restframework CBV试图的4种方式
查看>>
大图居中,以1920px为例
查看>>
Python3 图片转字符画
查看>>
[C陷阱和缺陷] 第7章 可移植性缺陷
查看>>