my java note ---- 内部类

本文深入探讨Java内部类的概念,包括成员内部类、局部内部类、匿名内部类和静态内部类等不同类型的特点与应用场景。同时,文章还介绍了如何从内部类继承及内部类之间的继承关系。

# 参考: Thinking in Java 4th
# Inner Class

Inner Class   

  内部类的定义: 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。

1. 内部类的种类  

   1.1 成员内部类

      成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

package mytest;

public class InnerTest1 {
    String name = "OUT class name";
    private String privatepara = "this is private out param";
    static String staticpara = "this is static out param";
    
    public InnerTest1(){
        System.out.println("out Class1 is instanced");
    } 
    
    public String getname(){
        return this.name;
    }
    
    public String getinnername(){
        return this.new Inner1().name;
    }
    
    public class Inner1{
        String name = "INNER class1 name";
        public Inner1(){
            System.out.println("Inner Class1 is instanced");
        } 
        
        public String getname(){
            return this.name;
        }
        
        public void getoutpara(){
            System.out.println(privatepara);
            System.out.println(staticpara);
        }
        
        public String getoutname(){
            return InnerTest1.this.name;
        }
        public String callgetname(){
            return InnerTest1.this.getname();
        }
    }
}
Inner Class
  <Test Code>
package mytest;

public class Test1 {

    public static void main(String[] args) {
        InnerTest1 test1 = new InnerTest1();
        //成员内部类是依附外部类而存在的.如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
        InnerTest1.Inner1  testinner1 = test1.new Inner1();
        
        System.out.println(test1.getname());
        //在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问.
        System.out.println(test1.getinnername());
        
        //成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
        testinner1.getoutpara();
        
        /*当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。
         * 如果要访问外部类的同名成员,需要以下面的形式进行访问:
         * 1. 外部类.this.成员变量
         * 2. 外部类.this.成员方法
         */
        System.out.println(testinner1.getname());
        System.out.println(testinner1.getoutname());
        System.out.println(testinner1.callgetname());
    }

}
Test Code
   <Note>

      1. 成员内部类是依附外部类而存在的.如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
      2. 在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问.
      3. 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
      4. 当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。
          如果要访问外部类的同名成员,需要以下面的形式进行访问:
           1. 外部类.this.成员变量
           2. 外部类.this.成员方法
      5. 内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。
          如果成员内部类用private修饰,则只能在外部类的内部访问;
          如果用public修饰,则任何地方都能访问;
          如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;
          如果是默认访问权限,则只能在同一个包下访问。普通类只能被public和包访问两种权限修饰。

   Q:  我们现在知道一个内部类可以访问封装类的成员。这是如何实现的呢?

   A:  内部类必须拥有对封装类的特定对象的一个引用,而封装类的作用就是创建这个内部类。随后,当我们引用封装类的一个成员时,就利用那个(隐藏)的引用来选择那个成员。

    1.2 方法和作用域中的内部类     

  若我们在一个方法甚至一个任意的作用域内创建内部类。有两方面的原因促使我们这样做:
        (1) 我们准备实现某种形式的接口,使自己能创建和返回一个句柄。 // 内部类实现抽象接口
        (2) 要解决一个复杂的问题,并希望创建一个类,用来辅助自己的程序方案。同时不愿意把它公开。
                                                            ------ from Thinking in Java 4th      

  1.2.1 局部内部类

package mytest;

interface Destination { 
      String readLabel(); 
    } 

public class InnerTest2 {
    //一个方法的作用域中创建一个完整的类
    public Destination dest(String s) { 
        class PDestination 
            implements Destination { 
          private String label; 
          private PDestination(String whereTo) { 
            label = whereTo; 
          } 
          public String readLabel() { return label; } 
        } 
        return new PDestination(s); 
      } 
    
    // 在任意作用域内嵌套一个内部类
      private void internalTracking(boolean b) { 
          if(b) { 
              class TrackingSlip { 
                private String id; 
                TrackingSlip(String s) { 
                  id = s; 
                } 
                String getSlip() { return id; } 
              } 
              TrackingSlip ts = new TrackingSlip("slip"); 
              String s = ts.getSlip(); 
              System.out.println(s);
            } 
            // Can't use it here! Out of scope: 
            //! TrackingSlip ts = new TrackingSlip("x"); 
          } 

    public static void main(String[] args) {
        InnerTest2 p = new InnerTest2(); 
        Destination d = p.dest("Tanzania"); 
        System.out.println(d.readLabel());
        // Console output $->Tanzania 
        
        p.internalTracking(true);
        // Console output $->slip 
    }

}
Inner Class
     <Note>

          1. PDestination 类属于 dest()的一部分,而不是 InnerTest2 的一部分(注意可为相同目录内每个类内部的一个内部类使用类标识符 PDestination,这样做不会发生命名的冲突)。因此,PDestination 不可从 dest()的外部访问。请注意在返回语句中发生的上溯造型——除了指向基础类 Destination 的一个句柄之外,没有任何东西超出 dest()的边界之外。当然,不能由于类 PDestination 的名字置于 dest()内部,就认为在dest()返回之后 PDestination 不是一个有效的对象。
          2. TrackingSlip 类嵌套于一个 if 语句的作用域内。这并不意味着类是有条件创建的——它会随同其他所有东西得到编译。然而,在定义它的那个作用域之外,它是不可使用的。

    3. 若试图定义一个局部内部类,并想使用在局部内部类外部定义的一个对象,则编译器要求外部对象为 final属性。<具体见1.2.2>

     1.2.2 匿名内部类-----属于局部内部类

    public Contents cont() {
       return new Contents() {
        private int i = 11;
        public int value() { return i; }
      };
    上面的代码要表达的意思是 :创建从 Contents 衍生出来的匿名类的一个对象”。由 new 表达式返回的句柄会自动上溯造型成一个 Contents 句柄。匿名内部类的语法其实要表达的是:
        class MyContents extends Contents {
            private int i = 11;
           public int value() { return i; }
        }
        return new MyContents();

package mytest;

interface Contents { 
    strvalue value(); 
    int count();
    String tostr();
    }

class strvalue{
    String str;
}

public class InnerTest3 {

    public Contents cont(final strvalue name,final int count,final String str) { 
        return new Contents() { 
          private String j = str;//assign value
          public strvalue value() { name.str = name.str+" world";return name; } 
          public int count() {  //count++; final data can not be change
              return count; } 
          public String tostr(){ //str = new String("hello world");
              // The final local variable str cannot be assigned,
              //since it is defined in an enclosing type
              return str; }
        }; // Semicolon required in this case 
      } 
      public static void main(String[] args) { 
        InnerTest3 p = new InnerTest3();
        strvalue str = new strvalue();
        str.str ="hello";
        int count = 1;
        String k = new String("teststring");
        System.out.println("input str >> "+str);
        System.out.println("input str >> "+str.str);
        System.out.println("input count >> "+count);
        Contents c = p.cont(str,count,k); 
        System.out.println("Content.values() >> "+c.value().str);
        System.out.println("Content.count() >> "+c.count());
        System.out.println("str >> "+str);
        System.out.println("str >> "+str.str);
        System.out.println("count >> "+count);
      } 
}
// OutPut:
//    input str >> mytest.strvalue@2a139a55
//    input str >> hello
//    input count >> 1
//    Content.values() >> hello world
//    Content.count() >> 1
//    str >> mytest.strvalue@2a139a55
//    str >> hello world
//    count >> 1
Inner Class
     <Note>

      1.     若想对匿名内部类的一个对象进行某种形式的初始化,此时会出现什么情况呢?由于它是匿名的,没有名字赋给构建器,所以我们不能拥有一个构建器。然而,我们可在定义自己的字段时进行初始化。

      2.     若试图定义一个匿名内部类,并想使用在匿名内部类外部定义的一个对象,则编译器要求外部对象为 final属性。这正是我们将 cont()的自变量设为 final 的原因。如果忘记这样做,就会得到一条编译期出错提示。

      3.     cont()方法中的参数name 是final的,但由于它是对象,所以只要其索引地址不变,内部的object类型属性的值是可以变化的。

1.3 Static 内部类

    通常可以认为内部类的对象默认持有创建它的那个封装类的一个对象的句柄。然而,假如我们说一个内部类是 static 的,这种说法却是不成立的。static 内部类意味着:
    (1) 为创建一个 static 内部类的对象,我们不需要一个外部类对象。
    (2) 不能从 static 内部类的一个对象中访问一个外部类对象。所以Static 内部类不能使用外部类的非static成员变量或者方法。

package mytest;

public class InnerTest{
    protected static class PDestination  { 
        private static String version = "1.1";
        private String label; 
        private PDestination(String whereTo) { 
          label = whereTo; 
        } 
        public String readLabel() { return label; } 
        } 
    
    public static PDestination dest(String s) { 
        return new PDestination(s); 
    } 
    public static void main(String[] args) { 
        PDestination d = dest("Tanzania");
        System.out.println(PDestination.version);
        System.out.println(d.readLabel());
    } 
}
Inner Class
 <Note>

  1. 创建静态内部类对象的一般形式为:  外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()。

  2. 创建成员内部类对象的一般形式为:  外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()。

  3. 局部内部类和匿名内部类由于作用域原因不能在外部类外面创建实例对象。

2. 从内部类继承

由于内部类构建器必须同封装类对象的一个句柄联系到一起(Static静态内部类除外),所以从一个内部类(成员内部类)继承的时候:
  1)成员内部类的引用方式必须为 Outter.Inner.
  2)构造器中必须有指向外部类对象的引用,并通过这个引用调用super()。

<Code>
class WithInner { 
  class Inner {} 
} 
 
public class InheritInner  
    extends WithInner.Inner { 
  //! InheritInner() {} 
  // 不能通过编译的,一定要加上形参(外部类对象)
  InheritInner(WithInner wi) { 
    wi.super(); //必须有这句调用
  } 
  public static void main(String[] args) { 
    WithInner wi = new WithInner(); 
    InheritInner ii = new InheritInner(wi); 
  } 
}
Inner Class
 

3. 内部类的继承

若衍生类与基础类均有同名的成员内部类且衍生类的内部类明确继承基类的内部类,则完成继承语法。

<Code>

class Egg2 { 
    protected class Yolk {  
        public Yolk() { 
            System.out.println("Egg2.Yolk()"); 
        } 
        public void f() { 
            System.out.println("Egg2.Yolk.f()"); 
        } 
    } 
    private Yolk y = new Yolk(); 
    public Egg2() { 
        System.out.println("New Egg2()"); 
    } 
    public void insertYolk(Yolk yy) { 
        System.out.println("insert begin..."); 
        y = yy; 
    } 
    public void g() { y.f(); } 
} 
     
public class BigEgg2 extends Egg2 { 
    public class Yolk extends Egg2.Yolk { 
        public Yolk() { 
          System.out.println("BigEgg2.Yolk()"); 
        }
        public void f() { 
          System.out.println("BigEgg2.Yolk.f()"); 
        } 
    } 
    public BigEgg2() { insertYolk(new Yolk()); } 
    public static void main(String[] args) { 
        Egg2 e2 = new BigEgg2(); 
        e2.g(); 
    } 
}
View Code

<OutPut>

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
insert begin...
BigEgg2.Yolk.f()

若仅仅是相同名字的内部类,没有明确继承则不算继承.

    private Yolk y;
    protected class Yolk{
        public Yolk(){
            System.out.println("Egg.Yolk");
        }
        public void f() { 
            System.out.println("Egg.Yolk.f()"); 
        } 
    }
    public Egg(){
        System.out.println("new Egg");
        y = new Yolk();
    }
    public void g() { y.f(); } 
}

public class BigEgg extends Egg{
    public class Yolk{
        public Yolk(){
            System.out.println("BigEgg.Yolk");
        }
        public void f() { 
            System.out.println("BigEgg.Yolk.f()"); 
        } 
    }
    public static void main(String[] args){
        new BigEgg().g();;
    }
}
View Code

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

new Egg
Egg.Yolk
Egg.Yolk.f()

转载于:https://www.cnblogs.com/ct-blog/p/5584517.html

标题基于Python的自主学习系统后端设计与实现AI更换标题第1章引言介绍自主学习系统的研究背景、意义、现状以及本文的研究方法和创新点。1.1研究背景与意义阐述自主学习系统在教育技术领域的重要性和应用价值。1.2国内外研究现状分析国内外在自主学习系统后端技术方面的研究进展。1.3研究方法与创新点概述本文采用Python技术栈的设计方法和系统创新点。第2章相关理论与技术总结自主学习系统后端开发的相关理论和技术基础。2.1自主学习系统理论阐述自主学习系统的定义、特征和理论基础。2.2Python后端技术栈介绍DjangoFlask等Python后端框架及其适用场景。2.3数据库技术讨论关系型和非关系型数据库在系统中的应用方案。第3章系统设计与实现详细介绍自主学习系统后端的设计方案和实现过程。3.1系统架构设计提出基于微服务的系统架构设计方案。3.2核心模块设计详细说明用户管理、学习资源管理、进度跟踪等核心模块设计。3.3关键技术实现阐述个性化推荐算法、学习行为分析等关键技术的实现。第4章系统测试与评估对系统进行功能测试和性能评估。4.1测试环境与方法介绍测试环境配置和采用的测试方法。4.2功能测试结果展示各功能模块的测试结果和问题修复情况。4.3性能评估分析分析系统在高并发等场景下的性能表现。第5章结论与展望总结研究成果并提出未来改进方向。5.1研究结论概括系统设计的主要成果和技术创新。5.2未来展望指出系统局限性并提出后续优化方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值