基础学习day09--内部类

一、内部类

1.1、内部类概念

定义在一个类内部中的另一个类,被称为内部类

特点:

可以直接访问,内部类的外部类中的,成员属性和方法(包含-private)

外部类要访问内部类中的成员和方法,需要先建立内部类对象

1.2、示例

package com.day08.innerclass.demo1;
/**
 * 包含内部类
 * @author denny
 *
 */
public class Outer { //外部类
    
    //private成员
    private String name="张三";
    private int age=20;
    private String gender="男";
    
    /**
     * 内部类
     */
    class Inner{
        private int num=3;
        
        public void hello(){
            System.out.println("姓名:"+name+"年龄:"+age
                    +"性别:"+gender);
        }
        public int getNum() {
            return num;
        }
        public void setNum(int num) {
            this.num = num;
        }
        
        
    }
    
    
    
    /*
     * 外部类中的方法
     */
    public void show(){
        System.out.println("姓名:"+this.name+"年龄:"+this.age
                +"性别:"+this.gender);
    }
    
    /*
     * 调用内部类
     */
    public void say(){
        Inner inner=new Inner();
        System.out.println("调用内部类:"+"num="+inner.getNum()+",  num="+inner.num);
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    
}

测试外部类

package com.day08.innerclass.demo1;

public class OuterTest {

    public static void main(String[] args) {
        //外部类调用内部类
        Outer o=new Outer();
        o.show();
        o.say();

    }

}

结果:

姓名:张三年龄:20性别:男
调用内部类:num=3, num=3

测试内部类

package com.day08.innerclass.demo1;

public class InnerTest1 {

    public static void main(String[] args) {
        // 声明内部类中对 象,先声明外部类,再声明内部类
        Outer.Inner inner = new Outer().new Inner();
        inner.hello();

    }

}

姓名:张三年龄:20性别:男
调用内部类:num=3, num=3

1.3、静态内部类

如果内部类是static修饰的就只能调用父类中static成员

声明方式,可直接外部类.内部类()来声明或者调用

package com.day08.innerclass.demo3;

public class Outer {
    //private成员
        private String name="张三";
        static int age=20;
        private String gender="男";
        
        /*
         * 外部类中的方法
         */
        public void show(){
            System.out.println("姓名:"+this.name+"年龄:"+this.age
                    +"性别:"+this.gender);
        }
        /**
         * 内部类
         */
        static class Inner{
            private int num=3;
            
            public void hello(){
                System.out.println("外部类年龄:"+age
                        +",内部类属性"+this.num);
            }
            }
        public static void main(String[] args) {
            //静态内部类可以直接通过外部类.内部类声明
            Outer.Inner inner=new Outer.Inner();
            inner.hello();
        }
}

外部类年龄:20,内部类属性3

1.4、内部类成员是static的话

这个内部类必须被static修饰,static只能调用外部类和内部类中的stiatic的成员.

package com.day08.innerclass.demo3;

public class Outer {
    //private成员
        private String name="张三";
        static int age=20;
        private String gender="男";
        
        /*
         * 外部类中的方法
         */
        public void show(){
            System.out.println("姓名:"+this.name+"年龄:"+this.age
                    +"性别:"+this.gender);
        }
        /**
         * 内部类
         */
         static class Inner{
            private  static int num=3;
            
            public static void hello(){
                System.out.println("外部类年龄:"+age
                        +",内部类属性"+num);
            }
            }
        public static void main(String[] args) {
            //静态内部类m成员也是静态的可以直接调用
            Outer.Inner.hello();
        }
}

结果:外部类年龄:20,内部类属性3

1.5、声明在外部类中成员方法中的内部类

声明成员方法中的,内部类,调用成员方法中的局部变量 时,成员方法中的局部变量 必须为final修饰

package com.day08.innerclass.demo3;

public class Outer {
    // private成员
    private String name = "张三";
    static int age = 20;
    private String gender = "男";

    /*
     * 外部类中的方法
     */
    public void show(int x) {
        final int y = 5;
        //System.out.println("姓名:" + this.name + "年龄:" + this.age + "性别:" + this.gender);
        class Inner {
            public void hello() {
                System.out.println("hello-------"+x + " ," + y);
            }
        }
        Inner inner = new Inner();
        inner.hello();
    }

    /**
     * 内部类
     */

    public static void main(String[] args) {
        //声明成员方法中的,内部类,调用成员方法中的局部变量 时,成员方法中的局部变量 必须为final修饰
        new Outer().show(8);
    }
}

hello-------8 ,5

1.6、为什么内部类能直接访问外部类中的成员呢?

因为内部类持有了外部类的引用,外部类名.this。  (默认省略)
package com.day08.innerclass.demo4;

public class Outer {
    private int num=3;
    
    class Inner{
        private int num=4;
        
        public void show(){
            int num=5;
            //局部变量
            System.out.println(num);
            //内部类的成员变量
            System.out.println(this.num);
            //外部类的成员变量 
            System.out.println(Outer.this.num);
        }
    }
    public static void main(String [] args){
        new Outer().new Inner().show();
    }

}

二、匿名内部类

2.1、匿名内部类概念 

内部类可以继承或实现一个外部类或者接口。

格式:
    new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
    简单理解:
    就是建立一个带内容的外部类或者接口的子类匿名对象。
    什么时候使用匿名内部类呢?
    通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。
    好处:
    增强阅读性。

2.2、重写类中的方法

package com.day08.innerclass.demo5;
/**
 * 抽象类
 * @author denny
 *
 */
public abstract class Person {
    
    private String name="张三";
    
    public void show(){
        System.out.println(this.name);
        
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    

}
package com.day08.innerclass.demo5;

/**
 * 外部类
 * 
 * @author denny 实现有一个方法的抽象类的匿名内部类
 *
 */
public class Outer {
    private int num = 3;

    public void say() {
        new Person() {// 匿名内部类
            public void show() {  //重写抽象类中的方法,抽象方法,普通方法都可以
                System.out.println("..............." + num);
            }
        }.show(); //对象创建完成,调用自己
    }

    public static void main(String[] args) {
        new Outer().say();
    }
}

结果:

...............3

第二种写法,适后重写了多个方法

package com.day08.innerclass.demo5;

/**
 * 外部类
 * 
 * @author denny 实现有一个方法的抽象类的匿名内部类
 *
 */
public class Outer {
    private int num = 3;

    public void say() {
        Person person=new Person() {// 匿名内部类
            public void show() {  //重写抽象类中的方法,抽象方法,普通方法都可以
                System.out.println("..............." + num);
            }
        };
        //对象创建完成
        person.show();
    }

    public static void main(String[] args) {
        new Outer().say();
    }
}

2.3、示例使用接口的方式

package com.day08.innerclass.demo6;
/**
 * 接口
 * @author denny
 *
 */
public interface BirdPro {
    
    /**
     * 2个抽象方法
     */
    public void shout();
    
    public void accact();

}

package com.day08.innerclass.demo6;

public class Outer {
    private String name="张三";
    
    public void show(){
        int y=3;
        BirdPro birdPro=new BirdPro(){
            //实现接口中的方法
            @Override
            public void shout() {
                System.out.println(name+","+y);
                
            }

            @Override
            public void accact() {
                System.out.println(y+","+name);
                
            }
            
            
        };
        birdPro.shout();
        birdPro.accact();
    }
    

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public static void main(String[] args) {
        new Outer().show();
    }
}

结果:

张三,3
3,张三

2.4、把匿名内部类做参数传递

  1. 通常的使用场景之一:
  2. 当函数参数是接口类型时,而且接口中的方法不超过三个。
  3. 可以用匿名内部类作为实际参数进行传递。
package com.day08.innerclass.demo6;

/**
 * 接口
 * 
 * @author denny
 *
 */
public interface BirdPro {

    /**
     * 2个抽象方法
     */
    public void shout();

    public void accact();

}
package com.day08.innerclass.demo6;

class InnerDemo {

    public static void main(String[] args) {
        // 把接口做参数传递
        show(new BirdPro() {
            // 实现接口中的方法
            @Override
            public void shout() {
                System.out.println("叫声");

            }

            @Override
            public void accact() {
                System.out.println("攻击");

            }

        });
    }

    public static void show(BirdPro birdPro) {// 做参数
        // 调用
        birdPro.accact();
        birdPro.shout();
    }
}

2.5、 初始化顺序

package com.day08.innerclass.demo2;

public class Fu {

    int num = 9;
    static{
        System.out.println(" static Fu");
    }

    {
        System.out.println("Fu");
    }

    Fu() {
        super();// Object
        // 显示初始化
        // 构造代码块初始化
        show(); // 构造函数调用方法,如果子类已经重写了,父类的方法,则执行子类的方法,但这时,成员还没有初初始化,所以为默认值
    }

    void show() {
        System.out.println("fu show " + num);// 被覆盖,运行子类的
    }

}
package com.day08.innerclass.demo2;

public class Zi extends Fu {
    int num = 8;
    static{
        System.out.println(" static Zi");
    }

    {
          System.out.println("Zi" );
    }

    Zi(){
           super();
           //显示初始化
           //构造代码块初始化
          show();
    }

     void show(){
          System.out.println("zi show " + num); 
     }
}
package com.day08.innerclass.demo2;

public class Test1 {

    public static void main(String[] args) {
        new Zi();

    }

}

结果:

static Fu
 static Zi
Fu
zi show 0
Zi
zi show 8

 

原文地址:https://www.cnblogs.com/liunanjava/p/4800707.html