内部类广泛意义上的四种分类

内部类

什么是内部类

在Java中,将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类,广泛意义上的内部类包含四种:成员内部类、局部内部类、匿名内部类和静态内部类。内部类提供了另类的Java不能多继承的解决方案,另外可以使我们能更优雅的去编写代码等

 

成员内部类:

  •       成员内部类是最基本的内部类,它是定义在另外一个类内部,这个类称为外部类
  •       成员内部类在编译完成后内部类名格式Outer$Inter.class,外部类 Outer.class
  •       一般情况下成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)

      但是当成员内部类拥有和外部类同名的成员变量或者方法时候,会发生隐藏现象,默认情况下访问的是成员内部类的成员,如果要访问外部类的同名成员,需要以下面形式访问

                                                                      外部类.this.成员变量/成员方法

 

权限问题     

可以把成员内部类看成成员来分析

如果成员内部类用private修饰,则只能在外部类中的内部类访问,如果用public 修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。而外部类只能用public 和包访问两种权限的,

 

如果外部类想访问内部类则要麻烦些,因为它还需要些条件,创建内部类的对象,再通过指向这个对象的引用来访问,如下:

class Outer {

    private String thing = null;

    public Outer(String thing) {

        this.thing = thing; //必须先创建成员内部类的对象,再进行访问

    }


   
    class Inter {     //内部类

        public void someThing() {

            System.out.println(thing);  //外部类的private成员,直接访问

        }

    }

}

                                                                                  这是一个成员内部类

成员内部类依附外部类存在,所以创建成员内部类对象,必须存在一个外部类的对象,创建成员内部类对象的一般方式如下:

public class Test {
    public static void main(String[] args)  {
        //第一种方式:
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
         
        //第二种方式:
        Outter.Inner inner1 = outter.someThing();
    }
}

另外当成员内部类用来作为继承的时候,要注意

      成员内部类的引用方式必须为Outter.Inner

      构造器中必须有指向外部类对象的引用,并通过这个引用调用super()。

 

局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内,或者该作用域内。

class Outer{//局部内部类
	
	void m1() {
		final int i=10;
		class Inter{
			
		 void m2() {
			 int i=100;
			 System.out.println( i+",2" );
		 }
		}
		System.out.println(i+",1");
		Inter inter=new Inter();
		inter.m2();
	}
	
	
}
public class Outter {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		 Outer outer=new Outer();
		 outer.m1();
	}

}

                                                                                  这是一个局部内部类

注意:局部内部类就像是方法里面的一个局部变量一样,是不能有public protected private 以及static修饰符的

我们要想访问局部内部类,首先要创建对象来访问内部类所在的方法中,再通过内部类的对象引用获取内部类中的方法,注意这里的成员变量用final修饰,局部内部类就想局部变量一样,随方法加载而加载,随方法结束而销毁.

 

匿名内部类

匿名内部类的特点

  • 不能定义任何静态成员/方法
  • 不能有抽象方法
  • 必须实现接口或抽象父类的所有抽象方法
  • 匿名内部类访问的外部类成员变量或成员方法必须用static修饰
interface Product//接口
{
  public int getPrice();
  public String  getName();
}

public class Test
{
  public void test (Product p)
  {
      System.out.println("姓名:"+p.getName()+"买了"+p.getPrice()+" $");
  }
  public static void main(String [ ] args )
    {
	  Test test1= new Test ();
          test1.test(new Product( )//实现接口并实现抽象方法
            {
               public int getPrice( )//实现方法
                 {
                    return 41;
                  }
                 public String getName( )//实现方法
                  {
                     return "张三 ";
                  }

            });
    }
}

看起来匿名内部类是十分的麻烦,确实,匿名内部类很麻烦,因为匿名内部类是唯一一种没有构造方法的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,但是在编写事件上使用匿名内部类方便,而且代码容易维护。像安卓开发,受系统内存影响,选用匿名内部类的方法最优。在有时候我们只需使用一次的时候,那我们就可以使用匿名内部类

静态内部类

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static,和其他类最大的区别就是静态内部类是不需要依赖于外部类,和静态成员变量类似,不能使用外部类的非static成员变量或者方法,因为在没有外部类的对象情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,外部类的非static成员必须依附于具体对象。

外部类调用静态内部类中的属性和方法

  •    通过创建静态内部类实例的方法来调用静态内部类的非静态属性和方法
  •    直接通过“ 外部类.内部类.属性(方法)” 的方式直接调用静态内部类中的静态属性和方法

创建静态内部类实例

  •    在非外部类中:外部类名.内部类名 name = new 外部类名.内部类名();
  •    在外部类中:内部类名 name = new 内部类名();


class Outer{
	 private int a=0;
	 private static int b=2; 
	static class StaticInter{
		 void inter() {
/*	System.out.println(a);  不能访问非静态成员,但是可以访问静态的如 b
*报错  Cannot make a static reference to the non-static field a
*/		
	System.out.println(b);		
		}
	}
	
	
}
 class Test{
	 public static void main(String[] args) {
		Outer.StaticInter inter=new Outer.StaticInter();
		inter.inter();//b的值    
	}
 }

贴一个静态很具体的实例讲解(https://www.cnblogs.com/Dean-0/p/11198112.html)

QA:

上述代码中理解下为什么局部内部类和匿名内部类只能访问局部final变量?

因为在局部的内部类中防止随着方法声明结束而结束生命周期,存在其他方法仍需要调用final的时候。另外变量会复制参数,如果不设置为final 则 无法确定生命周期,而这两个参数只改变一个的话,会造成数据不一致性,所以需要设置final。

(详情参考https://www.runoob.com/w3cnote/java-inner-class-intro.html) 菜鸟教程 -内部类

为什么在java中需要内部类?

  •   每个内部类都能独立的继承一个接口的实现,就可以实现java不能多继承的解决办法
  •   方便将存在一定逻辑关系的类组织在一起 ,又可以对外界隐藏。
  •   方便编写时间驱动程序
  •   方便编写线程代码

内部类中的变量问题?

class Outter//外部类

{

    private int a = 1;

    class Inner {//内部类

        private int a = 2;

        public void print() {

            int a = 3;

            System.out.println("局部变量:" + a);//本方法中

            System.out.println("内部类变量:" + this.a);//本类

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

        }

    }

}
public class Test {//测试类

    public static void main(String[] args)  {

        Outter outter = new Outter();

        outter.new Inner().print();

    }

}

 

结果:  321

 

 

 

 

                                                                                                                                 纯属个人理解,如果错误,还望指出.

个人学习周总结:

      这周的学习点,主要有两点内部类和常用类,内部类刚开始还是比较模糊的,不熟悉各种内部类的限制,在编写的时候总是出现小小的问题,缺少实际应用经验,这个还是多加使用才能熟练敲写,常用类这块,方法参数很多,比较复杂,都是很基础的内容,但是通过在API文档上查询使用方法,结合编程题食用效果很佳.总体来说,还是需要多加练习.

这一周,跟着老师学了很多,不过因为上课总容易分心,导致大多数的概念还是模糊,再加上缺少练习,在做题上还是很犹豫,但是通过一周自己概念的梳理和整理,思路已经理清,接下来就需要自己通过做题去多加练习.目前Java给我的概念就像是在用一堆的第三方类库和自己编写的工具类去编程,通过对类库的梳理来组成自己所能使用的功能.看看后期有没有其他的印象.为了后期实际开发中的功能模块,前期的基础还是需要打殷实.

后期的发展计划

  1. 打好Java基础知识,并熟记
  2. 列出目前为止出现的问题,一一解决 
  3. 梳理基础知识,结合实际情况做出应用
  4. 了解JVM运行底层,再往深发展
  5. 复习数据库及前端知识,结合新知识加深巩固

自勉吧

内部类广泛意义上的四种分类_第1张图片

 

内部类广泛意义上的四种分类_第2张图片

 

你可能感兴趣的:(java基础)