内部类分类以及使用

237 阅读4分钟

分为四类

  • 第一类:成员内部类
  • 第二类:局部内部类
  • 第三类:匿名内部类
  • 第四类:静态内部类

成员内部类

  1. 是一个最普通的内部类,相当于类中包含的一个成员属性或者是成员方法,基本格式:
    class Animal{
        String name="小狗狗";
        
        public Animal(String name){
            this.name=name;
        }
        
        class Pet{
            public void cry(){
                System.out.println("汪汪汪");
            }
        }
    }
    
    类Pet像Animal的一个成员,Animal是外部的一个大类,Pet是Animal的一个内部类。
  2. 可以访问外部类的所有属性或者是成员方法(其中包含私有变量和静态变量):
class Animal{
       private int age=12;
       public static double height=55.0;
       String name="小狗狗";
       
       public Animal(String name){
           this.name=name;
       }
       
       class Pet{
           public void cry(){
               System.out.println(age);//外部类的private成员
               System.out.println(height);//外部类的静态成员
           }
       }
   }

2.1 需要注意的是: 当内部类的变量或者方法和外部类的成员变量和方法名字一样的时候,使用this访问外部类的成员变量或者方法。

  1. 外部类要去访问成员内部类的成员就不那么容易了,需要先创建一个成员内部类的对象,然后通过只想这个对象的引用来访问:
class Animal{
       private int age=12;
       public static double height=55.0;
       String name="小狗狗";
       
       public Animal(String name){
           this.name=name;
           getCryInstance().cry();
       }
       
       private Pet getCryInstance(){
           return new Pet();
       }
       
       class Pet{
           public void cry(){
               System.out.println(age);//外部类的private成员
           }
       }
   }
  1. 但是想要创建一个成员内部类的对象的前提是先创建一个外部类的对象。下面是创建成员内部类的两种方式:
public class Test{
    public static void main(String[] args){
        //第一种方式:
        Animal outter=new Animal();
        Animal.Pet inner=outter.new Pet();
        
        //第二种方式:
        Animal.Pet inner1=outter.getPetInstance();
    }
    
    class Animal{
       private Pet pet=null;
       
       public Animal(){
       
       }
       
       public Pet getPetInstance(){
           if(pet==null){
               pet=new Pet();
           }
           return pet;
       }
       
       class Pet{
           public cry(){

           }
       }
   }
}

注意点: 成员内部类的访问权限的区间可以是private(只能是外部类访问内部成员),protected(只能在统同一包下或者继承了外部类的情况下进行访问),public(任何情况下都能访问)以及包访问权限(只能在同一包下的类可以访问),而外部类就只有public,以及包访问权限。

局部内部类

  1. 局部内部类定义在方法内部,相当于局部变量的存在,就只能在方法内或者说是在方法这个作用域内进行访问(局部内部类的实际例子):
class Animal{
       
    public Animal(){

    }
}
class Pet{
    public void getDog(){
        class Dog extends Animal{
            int age=11;
        }
        return new Dog();
    }
}

  1. 局部内部类不能被public,private,protected以及static修饰的(就类似于局部变量一样,局部变量是不需要被任何修饰符修饰的,因为局部变量仅仅局限于在方法内部进行访问)。

匿名内部类

  1. 匿名内部类顾名思义就是没有名字的内部类,如果想要让代码更加简洁,或者说只想使用一次那么就可以考虑匿名内部类,使用匿名内部类的一个前提条件是:继承一个父类或者是实现一个接口,下面是基本实现:
abstract class Animal{
    public abstract void eat();
}
public class Demo{
    public static void main(String[] args){
        Animal a=new Animal(){
            public void eat(){
                System.out.println("eat something);
            }
        };
        a.eat();
    }
}

我们可以看到上面的抽象类Animal中,我们直接把Animal中的方法在大括号中实现了,这便是匿名内部类。

  1. 在接口上怎样使用匿名内部类呢?
interface Animal{
    public void eat();
}
public class Demo{
    public static void main(String[] args){
        Animal a=new Animal(){
            public void eat(){
                System.out.println("eat something);
            }
        };
        a.eat();
    }
}
  1. 常用的情况: 实现多线程需要用到,因为如果要实现多线程必须继承Thread类或者是继承Runnable接口,(下面是Thread类的匿名内部类的实现):
public class Demo{
    public static void main(String[] args){
        Thread t=new Thread(){
            public void run(){
                for(int i=1;i<=6;i++){
                    System.out.println(i+" ");
                }
            }
        };
        t.start();
    }
}
//输出结果是1 2 3 4 5 6
  1. Runnable接口的匿名内部类的实现
public class Demo{
    public static void main(String[] args){
        Runnable r=new Runnable(){
            public void run(){
                for(int i=1;i<=6;i++){
                    System.out.println(i+" ");
                }
            }
        };
        Thread t=new Thread(t);
        t.start();
    }
}
//运行结果是1 2 3 4 5 6

静态内部类

public class Test{
    public static void main(String[] args){
        Animal.Dog dog=new Animal.Dog();
    }
}

class Animal{
    public Animal(){
    
    }
    
    static class Dog{
        public Dog(){
        
        }
    }
}
//如果是如下代码则会报错
class Animal{
    int age=11;
    static int count=6;
    public Animal(){
    
    }
    static class Dog{
        public Dog(){
            System.out.println(age);//这里会报错
            System.out.println(count);
        }
    }
}

看了代码之后,我们可以总结出静态内部类的特点:

  • 使用static修饰的的内部类称之为静态内部类
  • 内部类只属于外部类本身,不属于外部类的任何对象
  • 静态内部类不能访问外部类的实例成员,只能访问外部类的静态成员(或者说是类成员)
  • 外部类可以使用静态内部类的类名作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象访问其实例成员

当然,静态内部类还实现了雪花算法,但是小任有点累了,先去休息了,下次再把静态内部类实现单例模式的雪花算法太牛上吧,菜鸟,菜鸟,小任是菜鸟,小任才写博客没多久的时间,如果我有些错的地方希望大家能提醒一下哟,嘿嘿