Java知识(三):内部类与外部类的知识分析

缘由

最近复习了Java的一些基础知识,原因是想把Java的巩固基础知识的掌握程度,在翻看的一些基础知识的时候,发现有许多知识点都忘记了,只记得大概的要点,详细基本都记不起来了,这引起了我的重视,虽然做项目中用到技术都很先进,但是如果底层基础知识掌握的不够好或者是不够全面的话,对于所使用的技术不能够很好的理解其中的核心,刚好最近翻书看到了有关于内部类和外部类的一些知识和问题,原本我只知道内部类的分类和代码的形式,对其使用方式和使用规则并不了解,花了两天的时间总结了一些自己的见解和大牛的分析成果。

什么是内部类?

内部类的定义:

  1. 内部类提供了更好的封装性,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类

  2. 内部类成员可以直接访问外部类的私有数据,因为内部类被访问其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节,例如内部类的成员变量。

  3. 匿名内部类适合用于创建那些仅需要一次使用的类



代码格式:

class Outer{
    private String str ="外部类的字符串";
    //************************** 
    //定义一个内部类
    class Inner{
        private String inStr= "内部类的字符串";
        //定义一个普通方法
        public void print(){
            //调用外部类的str属性
            System.out.println(str);
            //调用内部类的inStr属性
            System.out.println(inStr);
        }
    }
    //************************** 
    //在外部类中定义一个方法,该方法负责产生内部类对象并调用print()方法
    public void fun(){
        //创建内部类对象
        Inner in = new Inner();
        //调用内部类对象提供的print
        in.print();
    }
}
public class Test{
    public static void main(String[] args)
    {
        //创建外部类对象
        Outer out = new Outer();
        //调用外部类方法
        out.fun();
    }
}

创建内部类的形式

  1. 在外部类外部 创建非静态内部类

    语法格式:外部类.内部类 内部类对象 = new 外部类().new 内部类();

    举例说明:Outer.Inner in = new Outer().new Inner();

  2. 在外部类外部 创建静态内部类

    语法格式:外部类.内部类 内部类对象 = new 外部类.内部类();

    举例说明:Outer.Inner in = new Outer().Inner();

  3. 在外部类内部 创建内部类语法

    语法格式:内部类 内部类对象 = new 内部类();

    举例说明:Inner in = new Inner();

外部类与内部类的访问格式

  1. 外部类访问内部类属性和方法:

    外部类需要通过内部类引用间接访问内部类元素,可以直接创建内部类对象对其内部属性和方法(非静态)进行访问

    Inner in = new Inner();

  2. 外部类访问内部类静态属性和方法:

    new OuterClass.new InnerClass.static_Field

    new OuterClass.new InnerClass.getMessage

  3. 调用静态内部类的静态属性和方法:

    new OuterClass.InnerClass.static_Field

    new OuterClass.InnerClass.getMessage

外部类和内部类之间的关系

  1. 内部类是一个编译时的概念,编译后外部类和其内部类生成两个独立的class文件:OuterClass.class和Outer$InnerClass.class
  2. 内部类可以直接访问外部类的属性和方法,但是外部类不能直接访问内部类的属性和方法
  3. 外部类可以通过内部类引用间接访问内部类属性和方法
  4. 对于静态内部类来说,静态内部类是不依赖于外部类的。也就说可以在不创建外部类对象的情况下创建内部类的对象

对于非静态的内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的

内部类可以直接访问外部类的元素(包括私有域)—外部类在内部类之前创建,创建内部类时会将外部类的对象传入

外部类可以通过内部类的引用间接访问内部类元素 — 要想访问内部类属性,必须先创建内部类对象

class Outer{
    //成员变量  与对象有关
    private String msg;
    private int age;
    //--------------------------
    class Inner{
        public void dispaly()
        {
            //此处有一个隐藏的Outer.this
            msg = "test";
            age = 20;
            System.out.println(msg);
            System.out.println(age);
        }
    }
    //--------------------------
    public void test()
    {
        Inner in = new Inner();
        in.dispaly();
    }
}
public class Test{
    public static void main(String[] args)
    {
        Outer out = new Outer();
        out.test();
    }
}

内部类是一个相对独立的个体,与外部类没有关系

class Outer{
    public void dispaly()
    {
        //外部类通过创建内部类的对象间接访问内部类元素
        Inner in = new Inner();
        in.dispaly();
    }
    class Inner{
        public void dispaly()
        {
            System.out.println("内部类");
        }
    }
}
public class Test1{
    public static void main(String[] args)
    {
        Outer out = new Outer();
        out.dispaly();
    }
}

内部类的分类

内部类的分类:成员内部类、静态内部类、局部内部类、匿名内部类

一、成员内部类

通俗的讲:就是在一个类的内部创建一个新的类,新创建的类成为内部类,内部类之外的类为外部类。

成员内部类形同成员方法,是外部类的一部分

  1. 成员内部类可以声明public、protected、private等访问限制,同时也可以声明abstract供其他类继承,或者声明为static、final和实现其它接口。

    (1).成员内部类可以声明public、protected、private等访问限制,同时也可以声明abstract供其他类继承,或者声明为static、final和实现其它接口。

    如果成员内部类用private修饰,则只能在外部类的内部访问

    如果成员内部类用public修饰,则任何和地方都能访问

    如果成员内部类用protected修饰,则只能在同一个包下或者继承其他外部类的情况下被访问

    如果成员内部类用默认修饰符,则只能在同一个包下被访问

    (2).成员内部类内部不允许存在任何static变量或方法,正如成员方法中不能有任何静态属性(成员方法与对象相关、静态属性与类有关)

    (3).成员内部类是依附外部类的,只有创建了外部类才能创建内部类

class Outer {
    private String name = "test";
    public  static int age =20;

    class Inner{
        public static int num =10;//错误写法
        //正确写法  public int num=10;
        public void fun()
        {
            System.out.println(name);
            System.out.println(age);
        }
    }
}
public class Test{
    public static void main(String [] args)
    {
        
    }
}

1、成员内部类与外部类的调用方式

  1. 成员内部类–>外部类示例:
public class Test {
	int x = 9;
	
	class Inner{
		int x = 8;
		public void test() {
			int x = 7;
			System.out.println(x);
			System.out.println(this.x);
			System.out.println(Test.this.x);
			test1();
		}
	}
	
	private void test1() {
		System.out.println("test");
	}
	public static void main(String [] args)
	    {
	      Inner in = new Test().new Inner();
	      in.test();
	    }
}`在这里插入代码片`
  1. 外部类的静态方法–>内部类的非静态方法
public class Test {
    class Inner{
        public void voice(){
            System.out.println("voice()");
        }
    }
    public static void test(){
        new Test().new Inner().voice();
    }
    public static void main(String[] args) {
      //主函数调用test方法
       test();13     }
}
  1. 非静态内部类的费静态方法–>外部类的静态方法
public class Test {
    class Inner{
        public void voice(){
            Test.this.test();
        }
    }
    public static void test(){
        System.out.println("test()");
    }
    public static void main(String[] args) {
    //主函数调用voice()
        Inner in = new Test().new Inner();
        in.voice();
    }
}
  1. 静态内部类的非静态方法–>外部类的非静态方法
public class Test {
	 static class Inner{
	        public void voice(){
	            new Test().test();
	        }
	    }
	    public void test(){
	        System.out.println("test()");
	    }
	    public static void main(String[] args) {
	    	//主函数调用voice()方法
	        new Test.Inner().voice();
	    }
}
  1. 外部类的非静态方法–>静态内部类的非静态方法
public class Outerclass {
    static class Inner{
        public void voice(){
            System.out.println("voice()");
        }
    }
    public void test(){
      //1、其他类访问外部类中的静态内部类的非静态方法
            new Outerclass.Inner().voice();
      //2、此处的Outerclass中的test方法访问静态内部类中的非静态方法
       new Inner().voice();
    }
    public static void main(String[] args) {
      //主函数调用test方法
        new Outerclass().test();
    }
}

二、静态内部类

关键字static可以修饰成员变量、方法、代码块、其实还可以修饰内部类,使用static修饰的内部类我们称之为静态内部类,静态内部类和非静态内部类之间存在一个最大的区别,非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外部类,但是静态类没有。

  1. 静态内部类的创建不需要依赖外部类可以直接创建
  2. 静态内部类不可以使用任何外部类的非staitc类(包括属性和方法),但可以存在自己的成员变量
  3. 静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态方法(方法,属性)。
  4. 静态内部类只能够访问外部类的静态成员,而非静态内部类则可以访问外部类的所有成员(方法,属性)
class Outer {
    public String name = "test";
    private static int age =20;

    static class Inner{
        private String name;
        public void fun()
        {
            System.out.println(name);
            System.out.println(age);
        }
    }
}
public class Test{
    public static void main(String [] args)
    {
        Outer.Inner in = new Outer.Inner();
    }
}

三、局部内部类

局部内部类顾名思义就是定义在方法里的类

  1. 局部内部类不允许使用访问修饰符(public、private、protect)均不允许
  2. 局部内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问(换句话说其他方法或者类都不知道有这个类的存在)方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它,其他地方均不能访问。
  3. 局部内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)
class Outer{
    private int num =5;
    //普通方法
    public void dispaly(int temp)
    {
        //方法内部类即嵌套在方法里面
        class Inner{
            public void fun()
            {
                System.out.println(num);
                temp++;
                System.out.println(temp);
            }
        }
        //方法内部类在方法里面创建
        new Inner().fun();
    }
}
public class Test{
    public static void main(String[] args)
    {
        Outer out = new Outer();
        out.dispaly(2);
    }
}

四、匿名内部类

匿名内部类就是一个没有名字的方法内部类,因此特点和方法与局部内部类完全一致,除此之外,还有自己的特点:

  1. 匿名内部类必须继承一个抽象类或者实现一个接口
  2. 匿名内部类没有类名,因此没有构造方法
  3. 匿名内部类没有访问修饰符
  4. 匿名内部类不存在任何静态成员或方法
匿名内部类主要是针对那些不能直接创建对象的抽象类和接口而来的,抽象类和接口没有构造器,不能创建实例化对象
//匿名内部类
//声明一个接口
interface MyInterface {
    //接口中方法没有方法体
    void test();
}
class Outer{
    private int num = 5;
    public void dispaly(int temp)
    {
        //匿名内部类,匿名的实现了MyInterface接口
        //隐藏的class声明
        //第一种写法:
        new MyInterface()
        {
            public void test()
            {
                System.out.println("匿名实现MyInterface接口");
                System.out.println(temp);
            }
        }.test();
        
        //第二种写法:
        //如果MyInterface不是接口或者抽象类,而是一个普通的类,可以写成:
        //当然这种情形与规范有冲突,我也只是尝试一下是否可以这样写,结果真的可以
            MyInterface mi = new MyInterface(){
            public void test(){
                System.out.println("匿名实现MyInterface接口");
                System.out.println(temp);
            }
        };
        mi.test();
        
    }
}
public class Test{
    public static void main(String[] args)
    {
        Outer out = new Outer();
        out.dispaly(3);
    }
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值