java学习笔记9--内部类总结
java学习笔记系列:
本文地址:http://www.cnblogs.com/archimedes/p/java-study-note9.html,转载请注明源地址。
java内部类分为: 非静态内部类、静态内部类、局部内部类、匿名内部类
内部类的共性:
(1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。
(2)内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。
(3)内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。
java 中的内部类和接口加在一起,可以的解决常被 C++ 程序员抱怨 java 中存在的一个问题:没有多继承。实际上,C++ 的多继承设计起来很复杂,而 java 通过内部类加上接口,可以很好的实现多继承的效果。
非静态内部类
当一个类作为另一个类的非静态成员,则这个类就是一个非静态内部类。
创建非静态内部类是很容易的,只需要定义一个类让该类作为其他类的非静态成员。该非静态内部类和成员变量或者成员方法没有区别,同样可以在非静态内部类前面加可以修饰成员的修饰符。创建非静态内部类的基本语法如下所示:
class OutClass {
    class InClass {
        //内部类成员
    }
    //外部类成员
}
在内部类的程序中,是经常会进行外部类和内部类之间访问的。在外部类中访问内部类是很容易的,只要把内部类看成一个类,然后创建该类的对象,使用对象来调用内部类中的成员就可以了。
在外部类中访问内部类的程序--举个例子:
class OutClass {
    class InClass {    //创建非静态内部类
        int i = 5;    //内部类成员
    }
    public void fun() {    //外部类成员
        InClass in = new InClass();    //创建一个内部类对象
        int i = in.i;        //访问内部类成员
        System.out.println("InClass's var is: " + i);
    }
}
public class javatest {
    public static void main(String args[ ]) {
         OutClass out = new OutClass();
         out.fun();
   }
}
运行结果:
InClass's var is: 5
分析:在main方法中,首先创建一个外部类对象,然后访问外部类的成员方法。在外部类的成员方法中,创建了一个内部类对象,然后使用内部类对象调用内部类的成员变量,从而得到结果。编译该程序将产生三个class文件,分别是主类、外部类和内部类。内部类产生的class文件的名称为OutClass$InClass.class,在该名称中可以区分该内部类到底是哪一个类的内部类。
不但可以在外部类中访问内部类,还可以在外部类外访问内部类。在外部类外访问内部类的基本语法如下所示。
OutClass.InClass oi=new OutClass().new InClass();
使用该方法就能够创建一个内部类对象,使用该内部类对象就可以访问内部类的成员。该方法是不容易理解的,可以分为下面的两条语句:
Wai w=new Wai();
Wai.Nei wn=w.new Nei();
这样就很容易理解了。首先是创建一个外部类的对象,然后让该外部类对象调用创建一个内部类对象。
在外部类外访问内部类的程序--举个例子:
class OutClass {
    class InClass {    //创建非静态内部类
        int i = 5;    //内部类成员
        int j = 6;
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass.InClass oi1 = new OutClass().new InClass();
        OutClass ocClass = new OutClass();
        OutClass.InClass oi2 = ocClass.new InClass();
        System.out.println("InClass's var i is: " + oi1.i);
        System.out.println("InClass's var j is: " + oi1.j);
   }
}
在示例代码中使用了两种方法来从外部类外访问内部类。在外部类外访问内部类时,是不能够直接创建内部类对象的,因为内部类只是外部类的一个成员。所以要想创建内部类对象,首先要创建外部类对象,然后以外部类对象为标识来创建内部类对象。
在内部类中访问外部类
在内部类中访问外部类,就像所有的同一个类中成员互相访问一样,这样是没有限制的,包括将成员声明为private私有的。
举个例子:
class OutClass {
    int i = 8;    //外部类成员变量
    class InClass {    //创建非静态内部类
        public void fun() {
            System.out.println("OutClass's var is: " + i);
        }
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass oc = new OutClass();    //创建外部类对象
        OutClass.InClass oi = oc.new InClass();    //创建内部类对象
        oi.fun();    //调用内部类中的成员
   }
}
在示例代码中,在内部类中定义了一个fun来访问外部类中的成员变量i。可以看到从内部类中访问外部类是非常容易的,不需要添加任何内容,就像成员方法间调用一样。如果外部类中也有一个成员变量i,得到的是内部类成员变量的值。下面通过示例代码解决这个问题:
class OutClass {
    int i = 8;    //外部类成员变量
    class InClass {    //创建非静态内部类
        int i = 9;
        OutClass oc = new OutClass();
        public void fun() {    //内部类成员
            System.out.println("InClass's var is: " + i);
            System.out.println("OutClass's var is: " + oc.i);
        }
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass oc = new OutClass();    //创建外部类对象
        OutClass.InClass ic = oc.new InClass();    //创建内部类对象
        ic.fun();    //调用内部类中的成员
   }
}
在本程序中先定义了一个外部类的成员变量,接着定义了一个内部类的成员变量,这两个成员变量的名称是相同的。而在内部直接访问时,将访问的是内部类的成员变量。要想访问外部类成员变量,就需要首先创建一个外部类对象,然后使用该对象调用外部类成员变量。
局部内部类
局部内部类的作用范围是和局部变量的作用范围相同的,只在局部中起作用,所以对局部内部类进行访问时,只能在该局部内部类的作用范围内。
举个例子:
class OutClass {
    public void fun() {
        class InClass {    //定义一个局部内部类
            int i = 5;    //局部内部类的成员变量
        }
        InClass ic = new InClass();
        System.out.println("InClass's var is: " + ic.i);
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass oc = new OutClass();
        oc.fun();
   }
}
在本程序中定义了一个局部内部类,并进行了对该局部内部类的访问。对该内部类进行访问必须在该内部类所在的方法中通过创建内部类对象来进行访问。这是因为这里的内部类是作为局部成员的形式出现的,只能在它所在的方法中进行调用。
局部内部类中访问外部类成员变量
在局部内部类中访问外部类成员变量是很容易实现的,并不需要进行过多操作。在局部内部类中可以直接调用外部类的成员变量。
举个例子:
class OutClass {
    int i = 9;    //定义一个外部类的成员变量
    public void fun() {
        class InClass {    //定义一个局部内部类
            public void Infun() {
                System.out.println("OutClass's var is: " + i);    //访问外部类中的成员变量
            }
        }
        InClass ic = new InClass();    //创建内部类对象
        ic.Infun();    //调用内部类中的成员方法
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass oc = new OutClass();    //创建外部类对象
        oc.fun();    //调用内部类中的成员
   }
}
在示例代码中定义了一个局部内部类,在该局部内部类中定义了一个方法来访问外部类的成员变量。
在局部内部类中访问外部类的局部变量
和访问外部类的成员变量不同,在局部内部类中访问外部类中和局部内部类在同一局部的局部变量是不能够直接访问的。
举个例子(下面是一段错误的代码):
class OutClass {
    public void OutFun() {
        int i = 9;
        class InClass {
            public void InFun() {
                System.out.println("OutClass's var is: " + i);//访问外部类的成员变量
            }
        }
        InClass ic = new InClass();    //创建内部类对象
        ic.InFun();    //调用内部类中的成员方法
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass oc = new OutClass();    //创建外部类对象
        oc.OutFun();    //调用内部类中的成员
   }
}
运行产生异常:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
	Cannot refer to a non-final variable i inside an inner class defined in a different method
运行该程序是会发生错误的,错误信息为“从内部类中访问局部变量i;需要被声明为最终类型”。在局部内部类中访问外部类的局部变量是不能够访问普通的局部变量的,必须将该局部变量声明为final。
静态方法中的局部内部类
局部内部类定义在非静态方法和静态方法中是不同的,在前面例子都是将局部内部类定义在非静态方法中,下面就来学习静态方法中定义局部内部类的情况。在静态方法中定义的局部内部类要想访问外部类中的成员,该成员必须是静态成员。
class OutClass {
    static int i = 4;
    public static void OutFun() {    //外部类成员
        class InClass {
            public void InFun() {
                System.out.println("OutClass's local var is: " + i);
            }
        }
        InClass ic = new InClass();
        ic.InFun();
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass.OutFun();
   }
}
静态内部类
class OutClass {
    static class InClass {
        //内部类成员
    }
    //外部类成员
}
在外部类中访问静态内部类
在外部类中访问静态内部类和在外部类中访问非静态内部类一样的,只需要从成员间访问的角度就可以考虑到这一点。举个例子:
class OutClass {
    static class InClass {    //创建静态内部类
        int i = 5;    //内部类成员
    }
    public void OutFun() {    //外部类成员
        InClass ic = new InClass();    //创建一个内部类对象
        int ii = ic.i;    //访问内部类成员
        System.out.println("static InClass's var is: " + ii);
    }
}
public class javatest {
    public static void main(String args[ ]) {
        OutClass oc = new OutClass();    //创建外部类对象
        oc.OutFun();    //调用内部类中的成员
   }
}
在外部类中访问静态内部类和访问非静态内部类是相同的,但是在外部类中访问静态内部类和非静态内部类就不再相同。因为静态内部类是外部类的静态成员,静态成员是不需要外部类对象而存在的,所以在外部类外,对静态内部类进行访问时是不需要创建外部类对象的。
注意:因为静态内部类是外部类的静态成员,静态成员是不需要外部类对象而存在的,所以在外部类外,对静态内部类进行访问时是不需要创建外部类对象的。
匿名内部类
在所有的内部类中最难的就应该是匿名内部类。匿名内部类从名字上看就知道是没有类名的内部类。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写,
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
创建匿名内部类
在创建匿名内部类中将使用到继承父类或者实现接口的知识,匿名内部类是没有名字的,所以在创建匿名内部类时同时创建匿名内部类的对象。创建匿名内部类的语法格式如下:
new InFather() {
    //匿名内部类
};
在创建匿名内部类的语法中,InFather是匿名内部类继承的父类的类名,使用new同时创建了匿名内部类的对象。在匿名内部类中可以重写父类中的方法,也可以定义自己的方法。
实例1:不使用匿名内部类来实现抽象方法
abstract class Person {
    public abstract void eat();
}
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
public class test {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}
运行结果:
eat something
可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类会很麻烦。这个时候就引入了匿名内部类
实例2:匿名内部类的基本实现
abstract class Person {
    public abstract void eat();
}
public class test {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}
运行结果:
eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了,这样便可以省略一个类的书写,并且匿名内部类还能用于接口上
实例3:在接口上使用匿名内部类
interface Person {
    public void eat();
}
public class test {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}
运行结果:
eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
实例4:Thread类的匿名内部类实现
public class test {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}
运行结果:
1 2 3 4 5
实例5:Runnable接口的匿名内部类实现
public class test {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}
运行结果:
1 2 3 4 5
参考资料:
1、http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html
java学习笔记9--内部类总结的更多相关文章
- Java学习笔记之---内部类
		Java学习笔记之---内部类 (一)成员内部类 内部类在外部使用时,无法直接实例化,需要借助外部类信息才能实例化 内部类的访问修饰符可以任意,但是访问范围会受到影响 内部类可以直接访问外部类的成员, ... 
- Java学习笔记:内部类/匿名内部类的全面介绍
		编写java程序时,一般一个类(或者接口)都是放在一个独立的java文件中,并且类名同文件名(如果类是public的,类名必须与文件名一致:非public得,无强制要求).如果想把多个java类放在一 ... 
- Java学习笔记之——内部类
		内部类 形式:把一个类定义在一个类的内部. 分为:成员内部类和匿名内部类重点掌握 a) 成员内部类 b) 静态成员内部类 c) 匿名内部类 d) 局部内部类 (1)成员内部类: Java的语言是面向对 ... 
- 3)Java学习笔记:内部类
		什么是内部类 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能使用public和 ... 
- 【原】Java学习笔记025 - 内部类
		package cn.temptation; public class Sample01 { public static void main(String[] args) { // 内部类(嵌套类): ... 
- 0035 Java学习笔记-注解
		什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ... 
- 0028 Java学习笔记-面向对象-Lambda表达式
		匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ... 
- 《Java学习笔记(第8版)》学习指导
		<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ... 
- 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类
		static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ... 
- Java学习笔记4
		Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ... 
随机推荐
- JAVA编程思想读书笔记(四)--对象的克隆
			接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ... 
- 初识GeneXus产品
			本人由于工作原因接触了GeneXus产品,从使用到现在也有些年头了.从刚开始的不熟悉到现在使用GeneXus开发了很多项目,慢慢也总结了一些经验,当然中间也走了很多的弯路.对于在国内同样使用GeneX ... 
- Trie树入门
			Trie树入门 貌似很多人会认为\(Trie\)是字符串类型,但是这是数据结构!!!. 详情见度娘 下面开始进入正题. PS:本文章所有代码未经编译,有错误还请大家指出. 引入 先来看一个问题  给 ... 
- HDU 6052 To my boyfriend(概率 贡献)
			To my boyfriend Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ... 
- Linux-数据库3
			外键约束 如果表A的主关键字是表B中的字段,则该字段称为表B的外键,表A称为主表,表B称为从表. 外键是用来实现参照完整性的,不同的外键约束方式将可以使两张表紧密的结合起来,特别是修改或者删除的级联操 ... 
- CUDA学习笔记2:CUDA(英伟达显卡统一计算架构)与已有的VS项目结合
			一.步骤 1.先新建一个简单的控制台应用程序,项目名称为Mytest,如下图所示: 2.在项目中添加一个名为Test.cu文件,如下图所示: 3.在解决方案资源管理器中选择该项目并点击右键,在弹出的菜 ... 
- wpf企业级开发中的几种常见业务场景
			前阵子在公司弄个内部的进销存管理系统,从了解需求.系统设计到编码,大约耗费了两个月时间,后来公司有了其他的安排,这东西就算黄了.顺便吐槽一下,厂里的一些人说话真心不顾别人感受,邮件啥的没一句舒服的.不 ... 
- [BZOJ2878][NOI2012]迷失游乐园(环套树DP+概率)
			推荐讲解:https://www.cnblogs.com/Tunix/p/4561493.html 首先考虑树的情况,就是经典的树上概率DP.先DP出down表示从这个点向儿子走能走的期望长度,再DP ... 
- MySql - GROUP BY 和 HAVING关键字
			本文主要针对GROUP BY 和 HAVING两个关键字进行分析 使用测试表如下: 测试前,只知道GROUP BY 这个关键字的作用是根据一个字段进行分组,去重.HAVING对分组设置条件. 具体分组 ... 
- apose 根据excel 导出模版
			string file = Server.MapPath("~/Excel/ZWxxtj.xls"); DataSet ds = new DataSet(); ... 
