ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

内部类

2022-04-10 22:32:21  阅读:130  来源: 互联网

标签:部类 内部 void public 访问 成员


内部类

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。 是我们类的第五大成员[思考:类的五大成员是哪些?[属性、方法、构造器、代码块、内部类],内部类最大的特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系, 注意:内部类是学习的难点,同时也是重点,看底层源码时,有大量的内部类。

基本语法
class Outer{ //外部类
	class Innter{//内部类
	
  }
}
class Other{//其他类
  
}
public class InnerClass01 { //外部其他类 
  public static void main(String[] args) {
  } 
}
class Outer { //外部类
  private int n1 = 100;//属性 
  public Outer(int n1) {//构造器
    this.n1 = n1; 
  }
  public void m1() {//方法 
    System.out.println("m1()"); 
  }
  {//代码块
    System.out.println("代码块..."); 
  }
  class Inner { 
    //内部类, 在 Outer类的内部
  }
}
内部类的分类

定义在外部类局部位置上(比如方法/代码块里面) :

  1. 局部内部类(有类名)
  2. 匿名内部类(没有类名,重点!!!!!)

定义在外部类的成员位置上:

  1. 成员内部类(没用static修饰)
  2. 静态内部类(使用static修饰)
局部内部类的使用

说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。 但是可以使用final修饰,因为局部变量也可以使用final

  3. 作用域:仅仅在定义它的方法或代码块中。

  4. 局部内部类---访问---->外部类的成员[访问方式:直接访问]

  5. 外部类---访问---->局部内部类的成员
    访问方式:创建内部类对象,再访问(注意:必须在内部类的作用域内创建对象)
    记住:

    (1)局部内部类定义在方法中/代码块
    (2)作用域在方法体或者代码块中
    (3)本质仍然是一个类(可以有类的五大成员)

  6. 外部其他类---不能访问---->局部内部类(因为局部内部类地位是一个局部变量)

  7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员) 去访问[演示]System.out.println(外部类的n2=”+外部类名this.n2);

public class LocalInnerClass {// 
  public static void main(String[] args) { //演示一遍
    Outer02 outer02 = new Outer02(); 
    outer02.m1(); 
    System.out.println("outer02 的 hashcode=" + outer02); 
  } 
}
class Outer02 {//外部类 
  private int n1 = 100; //属性
  private void m2() { //私有方法
    System.out.println("Outer02 m2()"); 
  }
  public void m1() {//共有方法 
    //1.局部内部类是定义在外部类的局部位置,通常在方法
    //3.不能添加访问修饰符,但是可以使用 final 修饰 
    //4.作用域: 仅仅在定义它的方法或代码块中 
    final class Inner02 {//局部内部类(本质仍然是一个类) 
      //2.可以直接访问外部类的所有成员,包含私有的
      private int n1 = 800; 
      public void f1() { 
        //5. 局部内部类可以直接访问外部类的成员,比如下面 外部类 n1 和 m2() 
        //7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员 
        //   使用 外部类名.this.成员 去访问外部类成员
        //   Outer02.this 本质就是外部类的对象
        //   哪个对象调用了m1, Outer02.this 就是哪个对象 (动态绑定机制)
        System.out.println("n1=" + n1 + " 外部类的 n1=" + Outer02.this.n1); 
        System.out.println("Outer02.this hashcode=" + Outer02.this); 
        m2(); //内部类可以访问 外部类的所有成员
      } 
    }
    //6. 外部类在方法中,可以创建 Inner02 对象,然后调用方法即可 
    Inner02 inner02 = new Inner02(); 
    inner02.f1(); 
  } 
}
匿名内部类的使用(重要!!!!!!!)
  1. 本质是类
  2. 内部类
  3. 该类没有名字
  4. 同时还是一个对象

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
1.匿名内部类的基本语法

new 类或接口(参数列表){
	类体
};
基于接口的匿名内部类
public class AnonymousInnerClass { 
  public static void main(String[] args) {
    Outer04 outer04 = new Outer04(); 
    outer04.method(); 
  } 
}
class Outer04 { //外部类 
  private int n1 = 10;//属性 
  public void method() {//方法 
    //基于接口的匿名内部类
    //1.需求: 想使用 IA 接口,并创建对象 
    //2.传统方式,是写一个类,实现该接口,并创建对象 
    //3.需求是 Tiger类只是使用一次,后面再不使用 
    //4. 可以使用匿名内部类来简化开发 
    //5. tiger 的编译类型 ? IA
    //6. tiger 的运行类型 ? 就是匿名内部类 Outer04$1
    /* 
    	底层会分配类名 Outer04$1
    	class Outer04$1 implements IA { 
    		@Override public void cry() { 
    			System.out.println("老虎..."); 
    		} 
    	} 
    */
  	//7. jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址 
    // 返回给 tiger 
    //8. 匿名内部类使用一次,就不能再使用
    IA tiger = new IA() { 
      @Override public void cry() { 
        System.out.println("老虎..."); 
      } 
    };
    System.out.println("tiger 的运行类型=" + tiger.getClass()); 		 
    tiger.cry(); 
  }
interface IA {//接口
  public void cry(); 
}
基于类的匿名内部类
class Father {//类
	public Father(String name) {//构造器
    System.out.println("接收到 name=" + name); 
  }
  public void test() {//方法 
  } 
}
//1. father 编译类型 Father 
//2. father 运行类型 Outer04$2 
//3. 底层会创建匿名内部类
/*
  class Outer04$2 extends Father{ 
    @Override public void test() { 
      System.out.println("匿名内部类重写了 test 方法"); 
    } 
  } 
*/
//4. 同时也直接返回了匿名内部类 Outer04$2 的对象 
//5. 注意("jack") 参数列表会传递给构造器 
Father father = new Father("jack"){
  @Override 
  public void test() { 
    System.out.println("匿名内部类重写了 test 方法"); 
  } 
};
System.out.println("father 对象的运行类型=" + father.getClass());//Outer04$2 
father.test();
基于抽象类的匿名内部类
abstract class Animal { //抽象类 
  abstract void eat(); 
}
Animal animal = new Animal(){ 
  @Override
  void eat() { 
    System.out.println("小狗吃骨头..."); 
  } 
};
animal.eat(); 
  1. 匿名内部类的语法比较奇特,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
  2. 可以直接访问外部类的所有成员,包含私有的
  3. 不能添加访问修饰符,因为它的地位就是一个局部变量。
  4. 作用域:仅仅在定义它的方法或代码块中。
  5. 匿名内部类---->访问---->外部类成员[访问方式]:直接访问
  6. 外部其他类---不能---->匿名内部类(因为匿名内部类地位是一个局部变量)
  7. 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
public static void main(String[] args) { 
  Outer05 outer05 = new Outer05(); 
  outer05.f1(); 
  //外部其他类---不能访问----->匿名内部类 
  System.out.println("main outer05 hashcode=" + outer05); 
	} 
}
class Outer05 { 
  private int n1 = 99;
  public void f1() { 
    //创建一个基于类的匿名内部类 
    //不能添加访问修饰符,因为它的地位就是一个局部变量 
    //作用域 : 仅仅在定义它的方法或代码块中 
    Person p = new Person(){
      private int n1 = 88; 
      @Override public void hi() {
        //可以直接访问外部类的所有成员,包含私有的 
        //如果外部类和匿名内部类的成员重名时,匿名内部类访问的话, 
        //默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问 
        System.out.println("匿名内部类重写了 hi 方法 n1=" +
                           n1 + " 外部内的 n1=" + Outer05.this.n1 ); 
        //Outer05.this 就是调用 f1 的 对象 
        System.out.println("Outer05.this hashcode=" + Outer05.this);
      }
    };
    p.hi();//动态绑定, 运行类型是 Outer05$1
    //也可以直接调用, 匿名内部类本身也是返回对象 
    // class 匿名内部类 extends Person {} 
    // 	new Person(){ 
    // 		@Override 
    // 			public void hi() { 
    // 				System.out.println("匿名内部类重写了 hi 方法,哈哈..."); 
    // 			} 
    // 		@Override 
    // 			public void ok(String str) { 
    // 				super.ok(str); 
    // 		} 
    // }.ok("jack"); 
  } 
}
class Person {//
  public void hi() { 
    System.out.println("Person hi()"); 
  }
  public void ok(String str) {
    System.out.println("Person ok()" + str); 
  } 
}
练习代码
public class InnerClassExercise01 { 
  public static void main(String[] args) { 
    //当做实参直接传递,简洁高效 
    f1(new IL() { 
      @Override public void show() { 
        System.out.println("这是一副名画~~..."); 
      } 
    }); 
    //传统方法 
    f1(new Picture()); 
 	} 
 //静态方法,形参是接口类型 
  public static void f1(IL il) { 
    il.show(); 
  } 
}
//接口 
interface IL { 
  void show(); 
}
//类->实现 IL => 编程领域 (硬编码) 
class Picture implements IL { 
  @Override public void show() { 
    System.out.println("这是一副名画 XX..."); 
  } 
}
练习代码
public static void main(String[] args) {
 Cellphone cellphone = new Cellphone();
  cellphone.alarmclock(new Bell(){
    @Override
    public void ring() {
      System.out.println("啦啦啦");
    }
  });
}
interface Bell{
  void ring();
}
class Cellphone{
  public void alarmclock(Bell bell){//接受的bell编译类型是Bell 运行类型是匿名内部类
    bell.ring;//动态绑定机制 调用的是匿名内部类的ring方法
  }
}
成员内部类的使用

说明:成员内部类是定义在外部类的成员位置上,并且没有static修饰。

  1. 可以直接访问外部类的所有成员,包含私有的
class Outer01{ //外部类
	private int n1 = 10;
	public String name = "张三";
	class Innter01 {//成员内部类
		public void say({
			System. out.printn( "Outer01的n1 = "+
                         n1 +”outer01的name=”+ name );
		}
   }
}
  1. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员。
  2. 作用域和外部类的其他成员样,为整个类体,比如前面案例,在外部类的成员方法中创
    建成员内部类对象,再调用方法.
  3. 成员内部类---访问--->外部类成员(比如:属性) [访问方式:直接访问] (说明)
  4. 外部类------->成员内部类(说明)访问方式:创建内部类对象,再访问
  5. 外部其他类-- ---->成员内部类
  6. 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员) 去访问
代码
public class MemberInnerClass01 { 
  public static void main(String[] args) { 
    Outer08 outer08 = new Outer08(); 
    outer08.t1(); 
    //外部其他类,使用成员内部类的三种方式 
    // 第一种方式 
    // outer08.new Inner08(); 相当于把 new Inner08()当做是 outer08 成员 
    // 这就是一个语法,不要特别的纠结.
    Outer08.Inner08 inner08 = outer08.new Inner08(); 
    inner08.say(); 
    // 第二方式 在外部类中,编写一个方法,可以返回 Inner08 对象 
    Outer08.Inner08 inner08Instance = outer08.getInner08Instance(); 
    inner08Instance.say(); 
  } 
}
class Outer08 { //外部类 
  private int n1 = 10; 
  public String name = "张三";
  private void hi() { 
    System.out.println("hi()方法..."); 
  } 
  //1.注意: 成员内部类,是定义在外部内的成员位置上 
  //2.可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员 
  public class Inner08 {//成员内部类 
    private double sal = 99.8; 
    private int n1 = 66; 
    public void say() { 
      //可以直接访问外部类的所有成员,包含私有的
      //如果成员内部类的成员和外部类的成员重名,会遵守就近原则. 
      //可以通过 外部类名.this.属性 来访问外部类的成员 
      System.out.println("n1 = " + n1 + 
                         " name = " + name + " 外部类的 n1=" + 
                         Outer08.this.n1); hi(); 
    } 
  }
  //方法,返回一个 Inner08 实例 
  public Inner08 getInner08Instance(){ 
    return new Inner08(); 
  }
  //写方法 
  public void t1() { 
    //使用成员内部类 
    //创建成员内部类的对象,然后使用内部类相关的方法和属性
    Inner08 inner08 = new Inner08(); 
    inner08.say(); 
    System.out.println(inner08.sal);
  } 
}
静态内部类的使用

说明:静态内部类是定义在外部类的成员位置,并且有static修饰

  1. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
  2. 可以添加任意访问修饰符(public、protected、 默认、private),因为它的地位就是一个成员。
  3. 作用域:同其他的成员,为整个类体
  4. 静态内部类--访向---外部类(比如:静态属性) [访问方式:直接访问所有静态成员]
  5. 外部类--访问----->静态内部类访问方式:创建对象,再访问
  6. 外部其他类--访问----- >静态内部类
  7. 如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员) 去访问
public class StaticInnerClass01 { 
  public static void main(String[] args) { 
    Outer10 outer10 = new Outer10(); 
    outer10.m1(); 
    //外部其他类 使用静态内部类 
    //方式 1 
    //因为静态内部类,是可以通过类名直接访问(前提是满足访问权限) 
    Outer10.Inner10 inner10 = new Outer10.Inner10(); 
    inner10.say(); 
    //方式 2 
    //编写一个方法,可以返回静态内部类的对象实例. 
    Outer10.Inner10 inner101 = outer10.getInner10(); 
    System.out.println("============"); 
    inner101.say();
    Outer10.Inner10 inner10_ = Outer10.getInner10_(); 
    System.out.println("************"); 
    inner10_.say(); 
  } 
}
class Outer10 { //外部类 
  private int n1 = 10; 
  private static String name = "张三"; 
  private static void cry() {} 
  //Inner10 就是静态内部类 
  //1. 放在外部类的成员位置 
  //2. 使用 static 修饰 
  //3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员 
  //4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员 
  //5. 作用域 :同其他的成员,为整个类体 
  static class Inner10 { 
    private static String name = "韩顺平教育"; 
    public void say() { 
      //如果外部类和静态内部类的成员重名时,静态内部类访问的时, 
      //默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员) 
      System.out.println(name + " 外部类 name= " + Outer10.name); 
      cry(); 
    } 
  }
  public void m1() { 
    //外部类---访问------>静态内部类 访问方式:创建内部类对象,再访问 
    Inner10 inner10 = new Inner10(); 
    inner10.say(); 
  }
  public Inner10 getInner10() { 
    return new Inner10(); 
  }
  public static Inner10 getInner10_() { 
    return new Inner10(); 
  } 
}

标签:部类,内部,void,public,访问,成员
来源: https://www.cnblogs.com/tzkf/p/16127871.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有