内部类的定义

1.内部类的定义

内部类是指在一个外部类的内部再定义一个类。

内部类可以是静态static的,也可用public,default,protected,private修饰。(而外部顶级类即类名和文件名相同的只能使用public和default)。

注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。

2.成员内部类

成员内部类,就是作为外部类的成员,可以直接使用外部类的所有成员和方法,即使是private的。同时外部类要访问内部类的所有成员变量/方法。则需要通过内部类的对象来获取。

要注意的是,成员内部类不能含有static的变量和方法。因为成员内部类需要先创建了外部类,才能创建它自己的。

package com.njwb.innerclass.use01;

public class Outer1 {

public int num1 = 10;

private int num2 = 33;

public void onlyTest(){

System.out.println("HelloWorld");

}

private int addNum(int a,int b){

return a+b;

}

public class Inner{

public int num1 = 20;

//成员内部类中不能出现static变量,static方法

//private static int num3 = 21;

/*private static void ceshi(){

}*/

public void onlyTest(){

System.out.println("Hello,tom");

}

public void print(){

System.out.println("num1="+num1);//内部类的成员变量(属性)和外部类同名时,内部类的成员变量有更高的优先级

System.out.println("访问外部类的私有变量"+"num2="+num2);//内部类可以任意访问外部类的属性,即使是私有的,也可以访问

System.out.println("调用外部类的私有访方法:"+addNum(11,11));

}

}

public Inner getInner(){

return new Inner();

}

public static void main(String[] args) {

//创建外部类对象

Outer1 out = new Outer1();

System.out.println(out.num1);

out.onlyTest();

System.out.println("-----------------");

//有内部类的对象才可以   内部类对象,借助外部类生成

//Inner in = out.new Inner();  //方式1

Inner in = out.getInner();  //方式2

//Inner in = new Inner(); //错误的

//想访问内部类的属性  

System.out.println(in.num1);

//想调用内部类的方法

in.onlyTest();

//变量同名时,调用的是内部类的变量

in.print();

}

}

3.局部内部类

局部内部类,是指内部类定义在方法和作用域(语句块中)内。

局部内部类也像别的类一样进行编译,但只是作用域不同而已,只在该方法或条件的作用域内才能使用,退出这些作用域后无法引用的。

方法内部类也有两个特点:

1) 方法中的内部类没有访问修饰符,即方法内部类对包围它的方法之外的任何东西都不可见。

2)方法内部类能够访问该方法中的局部变量,所以也叫局部内部类。而且这些局部变量一定要是final修饰的常量(访问的变量分为2类,1个是本方法中,1个是外部类中)。

例题1:

package com.njwb.innerclass.use01;

/**

 * 局部内部类 版本1 ,定义在方法中的类

 * @author Administrator

 *

 */

interface Destination{

}

public class Outer2 {

public Destination  generateDestination(){

//定义在方法内部的类 ,只在本方法内有效,超出本方法,对于外界不可见(外界访问不到)

class PDestination implements Destination{

private String label="hello";

public String readLabel(){

return this.label;

}

}

//创建内部类对象

PDestination d = new PDestination();

//调用内部类的方法

System.out.println(d.readLabel());

return d;

}

public void ceshi(){

//创建内部类对象

//PDestination d = new PDestination();

}

public static void main(String[] args) {

Outer2 out = new Outer2();

Destination d = out.generateDestination();

}

}

例题2:

package com.njwb.innerclass.use01;

/**

 * 局部内部类 ,定义在作用域中(语句块)

 * @author Administrator

 *

 */

public class Outer3 {

public void ceshi(boolean flag){

if(flag){

//int num=10;

//if作用域内创建1个类,只在if作用域内有效,其他地方都访问不到,即使本方法

class Inner{

private String label="hello";

public String readLabel(){

return label;

}

}

Inner in = new Inner();

System.out.println(in.readLabel());

}else{

System.out.println("flag="+flag);

//System.out.println("num="+num);  //else中访问不到ifnum变量

//Inner in2 = new Inner(); //同样道理

}

//System.out.println("num="+num); //本方法中也访问不到ifnum变量

}

public static void main(String[] args) {

Outer3 out = new Outer3();

out.ceshi(true);

}

}

例题3:

package com.njwb.innerclass.use01;

/**

 * 定义在方法中的局部内部类 ,局部内部类可以访问的变量的类型?

 * 1.如果访问本方法中的变量,该变量必须是final修饰的常量

 * 2.如果访问外部类中的变量,该变量的类型不限制

 * @author Administrator

 *

 */

public class Outer4 {

private int num2 = 33;

private static int num3 = 34;

public void ceshi(){

final int num1 = 12; //该变量必须用final修饰

class Inner{

public void printStr(){

System.out.println("num1="+num1);

System.out.println("num2="+num2);

System.out.println("num3="+num3);

}

}

//实例化内部类对象,调用内部类的方法

Inner in = new Inner();

in.printStr();

}

public static void main(String[] args) {

Outer4 out = new Outer4();

out.ceshi();

}

}

4.静态内部类

就是修饰为static的内部类。声明为static的内部类,不需要内部类对象和外部类对象之间的联系,就是说我们可以直接引用Outer.Inner,即不需要创建外部类对象,也不需要创建内部类对象。

静态内部类和普通的成员内部类还有一个区别:普通内部类不能有static属性和static方法,但静态内部类可以。静态内部类一般声明为public,方便调用。

静态内部类和普通的成员内部类最大的区别:静态内部类中无法引用到其外围类的非静态成员(既包含外部类的 成员变量,也包含外部类的成员方法)。

package com.njwb.innerclass.use02;

/**

 * 静态内部类: 可以出现静态的变量,静态的方法 ,普通内部类不可以

 * 1.静态内部类  不能访问外部类的非静态的成员(变量,方法)

 * 2.静态内部类的静态方法   外部类的类名.内部类的类名.内部类的方法名

 * 3.如果静态内部类中出现的普通方法,该如何调用? Outer1中 定义一个方法 返回该内部类对象  public Inner getInner(){}

 * 在测试中main方法中 ,通过Outer1 out = new Outer1(); 先获取到外部类的对象,再调用getInner()方法,获取到内部类对象

 * @author Administrator

 *

 */

public class Outer1 {

private int num2 = 20;

private static int num3 = 30;

public void ceshi1(){

System.out.println("测试1");

}

public static void ceshi2(){

System.out.println("测试2");

}

public static class Inner{

public static int num1=10;

public static void printStr(){

System.out.println("hello");

//静态内部类不能引用外部类的 非静态变量

//System.out.println("num2="+num2);

System.out.println("num3="+num3);

//静态内部类中调用外部类的方法 ,不能引用外部类的非静态方法

//ceshi1();

ceshi2();

}

public void innerCommonMethod(){

System.out.println("静态内部类Inner中定义的普通方法innerCommonMethod()");

}

}

public Inner getInner(){

return new Inner();

}

public static void main(String[] args) {

//调用静态内部类的方法

Outer1.Inner.printStr();

Outer1 out = new Outer1();

//获取到内部类的对象

Inner in = out.getInner();

//调用内部类的普通方法

in.innerCommonMethod();

}

}

4.匿名内部类

匿名内部类是不能加访问修饰符的。要注意的是,new 匿名类,这个类是要先定义的。

4.1.匿名内部类不带参数(掌握)

留意外部类的方法的形参,当所在的方法的形参需要被内部类里面使用时,该形参必须为final.

package com.njwb.innerclass.use02;

interface Inner21{

String getName();

}

public class Outer21 {

/**

 * name被内部类使用的,用final修饰 ,city没有被内部类使用,不用final修饰

 * @param name

 * @param city

 * @return

 */

public Inner21 getInner(final String name,String city){

class MyInner implements Inner21{

private String label = name;

@Override

public String getName() {

return label;

}

}

return new MyInner();

}

}

package com.njwb.innerclass.use02;

/**

 * 不带参的匿名内部类 和Outer21中的效果完全等价

 * 匿名内部类 :没有具体的类名,不加访问修饰符,以前所有放在类体里,都需要放在 匿名的那个类的花括号中{}

 * @author Administrator

 *

 */

interface Inner22{

String getName();

}

public class Outer22 {

/**

 * name被内部类使用的,用final修饰 ,city没有被内部类使用,不用final修饰

 * @param name

 * @param city

 * @return

 */

public Inner22 getInner(final String name,String city){

return new Inner22(){

private String label = name;

@Override

public String getName() {

return label;

}

};

}

}

这里可以看到形参name已经定义为final了,而形参city没有被使用则不用定义为final.

4.2匿名内部类带参数(掌握)

package com.njwb.innerclass.use02;

abstract class Inner31{

public Inner31(String name,String city) {

}

public Inner31() {

}

abstract String getName();

}

public class Outer31 {

public Inner31 getInner(String name,String city){

class MyInner extends Inner31{

private String label;

public MyInner(String name0,String city0) {

this.label = name0;

}

@Override

String getName() {

return label;

}

}

return new MyInner(name,city);

}

public static void main(String[] args) {

Outer31 out = new Outer31();

Inner31 in = out.getInner("jack", "nanjing");

System.out.println(in.getName());

}

}

package com.njwb.innerclass.use02;

abstract class Inner32{

public Inner32(String name,String city) {

}

abstract String getName();

}

public class Outer32 {

public Inner32 getInner(final String name,String city){

return new  Inner32(name,city){

private String label=name;

@Override

String getName() {

return label;

}

};

}

}

注意这里的形参city,由于它没有被匿名内部类直接使用,而是被抽象类Inner的构造函数所使用,所以不必定义为final

4.3匿名内部类通过实例初始化,可以达到类似构造器的效果

package com.njwb.innerclass.use02;

interface Inner41{

String getName();

String getCity();

}

public class Outer41 {

public Inner41 getInner(final String name,final String city){

class MyInner implements Inner41{

private String nameStr = name;

private String cityStr = city;

@Override

public String getCity() {

return cityStr;

}

@Override

public String getName() {

return nameStr;

}

}

return new MyInner();

}

public static void main(String[] args) {

Outer41 out = new Outer41();

//类似带参构造传入2个参数 类似 Inner41 in = new Inner41("jack","南京");

Inner41 in = out.getInner("jack", "南京");

//通过get方法获取属性的值 ,实质上也不是真正的get访问器,而是接口中定义的带返回值的抽象方法

System.out.println(in.getName());

System.out.println(in.getCity());

}

}

package com.njwb.innerclass.use02;

interface Inner42{

String getName();

String getCity();

}

public class Outer42 {

public Inner42 getInner(final String name,final String city){

return new Inner42(){

private String nameStr = name;

private String cityStr = city;

@Override

public String getCity() {

return cityStr;

}

@Override

public String getName() {

return nameStr;

}

};

}

public static void main(String[] args) {

Outer42 out = new Outer42();

Inner42 in  = out.getInner("jack", "南京");

System.out.println(in.getName());

System.out.println(in.getCity());

}

}

5.内部类的继承(了解)

内部类的继承,是指内部类被继承,普通类extends 内部类。而这时候代码上要有点特别处理。

package com.njwb.innerclass.use02;

/**

 * 内部类的继承 ,内部类可以是其他的类的父类

 * @author Administrator

 *

 */

class WithInner{

class Inner{

}

}

//父类为内部类Inner

class InheritInner extends WithInner.Inner{

//如果一个类继承了内部类,那么该类必须定义带参构造,参数必须传入内部类所在的外部类的对象

public InheritInner(WithInner wi) {

wi.super();

}

}

public class Outer5 {

public static void main(String[] args) {

WithInner wi = new WithInner();

InheritInner in = new InheritInner(wi);

}

}

可以看到子类的构造函数里面要使用父类的外部类对象.super();而这个对象需要从外面创建并传给形参。

内部类的特点总结

1) 在方法间定义的非静态内部类:

l 外围类和内部类可互相访问自己的私有成员

l 内部类中不能定义静态成员

2)在方法间定义的静态内部类:

l 只能访问外部类的静态成员。

3)在方法中定义的局部内部类:

l 该内部类没有任何的访问控制权限

外围类看不见方法中的局部内部类的(局部内部类的作用域),但是局部内部类可以访问外围类的任何成员。

l 方法体中可以访问局部内部类,但是访问语句必须在定义局部内部类之后。

局部内部类可以访问方法体中的常量,即用final修饰的成员。

4)在方法中定义的匿名内部类:

没有构造器,取而代之的是将构造器参数传递给超类构造器(匿名内部类创建的时候调用父类已经声明的带参构造器)。

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值