Java内部类

本文详细介绍了Java中的内部类,包括成员内部类、局部内部类和匿名内部类的定义、访问权限以及使用场景。内部类可以直接访问外部类的私有成员,提供数据隐藏和多继承的功能。同时,文章探讨了内部类在解决同名方法冲突和接口实现等问题上的作用,并给出了实例代码进行演示。
摘要由CSDN通过智能技术生成

概述

把类定义在另一个类的内部,该类就被称为内部类

  • 访问权限
  1. 内部类可以直接访问外部类的成员,包括私有。
  2. 外部类要想访问内部类成员,必须创建对象。
class Outer {
	private int num = 10;
	
	class Inner {
		public void show() {
			System.out.println(num);
		}
	}
	
	public void method() {
		//找不到符号
		//show();
	
		Inner i = new Inner();
		i.show();
	}
	
}

class InnerClassDemo {
	public static void main(String[] args) {
	
	}
}
  • 分类
  1. 成员内部类:在成员位置定义的类
  2. 局部内部类:在局部位置定义的类
  3. 匿名内部类

局部内部类与匿名内部类区别在于:局部内部类可以编写自己的构造方法。

成员内部类

  1. 成员内部类不是静态的:外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
  2. 成员内部类是静态的: 外部类名.内部类名 对象名 = new 外部类名.内部类名();
class Outer {
    //静态内部类访问的外部类数据必须用静态修饰。
    private static int num = 10;
    private int num2 = 20;

    public static class Inner {
        public void show() {
            System.out.println(num);
        }
    }

    class Inner2 {
        public void show() {
            System.out.println(num2);
        }
    }
}

class InnerClassDemo3 {
    public static void main(String[] args) {
        //成员内部类不是静态的
        Outer.Inner2 oi2 = new Outer().new Inner2();
        oi2.show();

        //成员内部类是静态的
        Outer.Inner oi = new Outer.Inner();
        oi.show();
    }
}

输出:
20
10

一般情况,成员内部类用private、static修饰,private:保证数据的安全性,static:方便访问数据。

class Body {
    private class Heart {
        public void operator() {
            System.out.println("心脏搭桥");
        }
    }

    public void method() {
        Heart h = new Heart();
        h.operator();
    }
}

Body b = new Body();
b.method();

输出:
心脏搭桥

局部内部类

  1. 可以直接访问外部类的成员
  2. 在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能。
class Outer {
    private int num  = 10;

    public void method() {
        //int num2 = 20;
        //final int num2 = 20;
        class Inner {
            public void show() {
                System.out.println(num);
                //从内部类中访问本地变量num2; 需要被声明为最终类型
                System.out.println(num2);//20
            }
        }

        //System.out.println(num2);

        Inner i = new Inner();
        i.show();
    }
}

class InnerClassDemo5 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

局部内部类访问局部变量的注意事项?
答:局部内部类访问的局部变量必须用final修饰。
因为局部变量是随着方法的调用而调用,随着调用完毕而消失。而堆内存的内容并不会立即消失。 如果内部类使用的局部变量清空,而自身堆内存还在使用,会导致不可预知错误。所以,使用final修饰局部变量,这个变量就成了常量。不影响内部类继续使用。

匿名内部类

内部类的简化写法。本质是一个继承了该类或者实现了该接口的子类匿名对象。简化类定义。

格式:
 new 类名或者接口名(){
  重写方法;
 }

class Outer {
    public void method() {
        //一个方法的时候
		/*
		new Inter() {
			public void show() {
				System.out.println("show");
			}
		}.show();
		*/

        //二个方法的时候
		/*
		new Inter() {
			public void show() {
				System.out.println("show");
			}
			
			public void show2() {
				System.out.println("show2");
			}
		}.show();
		
		new Inter() {
			public void show() {
				System.out.println("show");
			}
			
			public void show2() {
				System.out.println("show2");
			}
		}.show2();
		*/

        //如果很多个方法,就很麻烦了。可以使用临时引用调用。
        Inter i = new Inter() { //多态
            public void show() {
                System.out.println("show");
            }

            public void show2() {
                System.out.println("show2");
            }
        };
        i.show();
        i.show2();
    }
}

class InnerClassDemo6 {
    public static void main(String[] args) {
        Outer o = new Outer();
        o.method();
    }
}

输出:
show
show2

一般,匿名内部类在开发中的使用是作为参数传入

interface Person {
    public abstract void study();
}

class PersonDemo {
    //接口名作为形式参数
    //其实这里需要的不是接口,而是该接口的实现类的对象
    public void method(Person p) {
        p.study();
    }
}

//实现类
class Student implements Person {
    public void study() {
        System.out.println("好好学习,天天向上");
    }
}

class InnerClassTest2 {
    public static void main(String[] args) {
        //测试
        PersonDemo pd = new PersonDemo();
        Person p = new Student();
        pd.method(p);
        System.out.println("--------------------");

        //匿名内部类在开发中的使用
        //匿名内部类的本质是继承类或者实现了接口的子类匿名对象
        pd.method(new Person(){
            public void study() {
                System.out.println("好好学习,天天向上");
            }
        });
    }
}

面试题1:
要求请填空分别输出30,20,10。

class Outer {
    public int num = 10;
    class Inner {
        public int num = 20;
        public void show() {
            int num = 30;
            System.out.println(num);
            System.out.println(this.num);
            //System.out.println(new Outer().num);
            System.out.println(Outer.this.num);
        }
    }
}
class InnerClassTest {
    public static void main(String[] args) {
        Outer.Inner oi = new Outer().new Inner();
        oi.show();
    }
}

面试题2:
要求在控制台输出”HelloWorld”

interface Inter {
  void show();
}
class Outer {
  //补齐代码
}
class OuterDemo {
  public static void main(String[] args) {
    Outer.method().show();
  }
}

class Outer {
    //补齐代码
    public static Inter method() {
        //子类对象 -- 子类匿名对象
        return new Inter() {
            public void show() {
                System.out.println("HelloWorld");
            }
        };
    }
}

Outer.method()可以看出method()是类 Outer 中的一个静态方法Outer.method().show()可以看出method()方法的返回值是一个对象。又因为接口 Inter 中有一个 show() 方法,所以 method() 方法返回实现接口 Inter 的子类对象。

内部类的作用

1、内部类可以很好的实现隐藏

成员内部类用private、static修饰,private:保证数据的安全性,static:方便访问数据。

2、内部类可以访问外部类的所有属性

内部类拥有外围类的所有元素的访问权限

3、实现多重继承

个人认为它是内部类存在的最大理由之一。正是由于他的存在使得Java的继承机制更加完善。
Example1

public abstract class Example1 {
    public abstract String name();
}

Example2

public abstract class Example2 {
    public abstract int age();
}

MultiExample

public class MultiExample {
    private class test1 extends Example1 {
        @Override
        public String name() {
            return "shwen";
        }
    }

    private class test2 extends Example2 {
        @Override
        public int age() {
            return 29;
        }
    }

    public String name() {
        return new test1().name();
    }

    public int age() {
        return new test2().age();
    }

    public static void main(String args[]) {
        MultiExample mi = new MultiExample();
        System.out.println("姓名:" + mi.name());
        System.out.println("年龄:" + mi.age());
    }
}

输出:
姓名:shwen
年龄:29

MultiExample类包含内部类test1 test12test1类继承了Example1test2类继承了Example2,这样类MultiExample就拥有了Example1Example2的方法和属性,也就间接地实现了多继承。

4、区别继承的类和接口里同名方法

问题:Java是一门单继承语言,但是,在子类的继承关系中,会存在父类和接口有同名方法的情况,这种情况该怎么处理呢?

接口MyInterface

public interface MyInterface {
	void test();
}

父类Father

public class Father {
	public void test() {
		System.out.println("父类方法");
	}
}
public class Son extends Father implements MyInterface{}

子类没有重写接口方法test(),但是不报错。因为,子类默认继承了父类test()方法

修改一:如果将父类test()方法注释:

public class Father {
    /*public void test() {
        System.out.println("父类方法");
    }*/
}

在这里插入图片描述
需要子类实现接口中的方法。

修改二:将父类中方法取消注释,子类实现该方法,代码如下:

public class Father {
	public void test() {
		System.out.println("父类方法");
	}
}
public class Son extends Father implements MyInterface {
    public void test() {
        System.out.println("子类方法");
    }
}

请添加图片描述
可以看到,子类方法提示是重写父类方法 并且 实现接口方法。

继承的类和接口里面有两个同名的方法,默认重写继承父类的方法,那如果想重写接口的方法呢?怎么区分它们??
答:内部类

public class Son extends Father {
    public void test() {
        System.out.println("子类继承方法");
    }
    
    class test1 implements MyInterface {
        @Override
        public void test() {
            System.out.println("子类实现方法");
        }
    }

    MyInterface getMyInterface() {
        return new test1();
    }
}

我们可以用内部类test1来实现接口,这样就不会与外围类的方法冲突了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会叫的狼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值