首页 > 编程语言 > 详细

Java内部类

时间:2020-11-25 22:27:05      阅读:34      评论:0      收藏:0      [点我收藏+]

Java内部类详解

一、内部类基础

在java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类成为内部类。内部类通常分为四种:

  • 成员内部类
  • 局部内部类
  • 匿名内部类
  • 静态内部类

创建内部类

在外部类外部 创建非静态内部类
语法: 外部类.内部类 内部类对象 =  new 外部类().new 内部类();
  		Outer.Inner  inner   =  new Outer().new Inner();
在外部类外部 创建静态内部类
语法: 外部类.内部类  内部类对象  = new  外部类.内部类();
  		Outer.Inner inner     =   new Outer.Inner();

在外部类内部创建内部类语法

Inner in = new Inner();

1.成员内部类

成员内部类是最普通的内部类,它的定义为一个位于另一个类的内部,但是成员内部类不予许存在任何Static的变量或者方法

class Circle { //外部类
    double radius = 0;
    public Circle(double radius) {
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println("drawshape");
        }
    }
}

成员内部类可以无条件访问外部类所有的成员属性和成员方法(private和static也可以)

class Circle {//外部类
    private double radius = 0;
    public static int count =1;
    public Circle(double radius) {//有参构造
        this.radius = radius;
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println(radius);  //外部类的private成员
            System.out.println(count);   //外部类的静态成员
        }
    }
}

注意:当成员内部类拥有和成员外部类同名的变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部的同名成员,需要使用:

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

虽然成员内部类可以无条件的访问外部类的成员。而外部类想访问内部的成员就没有这么方便。

如果外部类中要访问内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个的对象来访问:

class Circle {
    private double radius = 0;
 
    public Circle(double radius) {
        this.radius = radius;
        getDrawInstance().drawSahpe();   //必须先创建成员内部类的对象,再进行访问
    }
     
    private Draw getDrawInstance() {
        return new Draw();
    }
     
    class Draw {     //内部类
        public void drawSahpe() {
            System.out.println(radius);  //外部类的private成员
        }
    }
}

成员内部类是依附于外部类存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象,创建成员内部类对象的一般方式:

ublic class Test {
    public static void main(String[] args)  {
        //第一种方式:
        Outter outter = new Outter();
        Outter.Inner inner = outter.new Inner();  //必须通过Outter对象来创建
         
        //第二种方式:
        Outter.Inner inner1 = outter.getInnerInstance();//通过一个方法返回一个inner的对象,本质上是一样的
    }
}
 
class Outter {//外部类
    private Inner inner = null;
    public Outter() {
         
    }
     
    public Inner getInnerInstance() {
        if(inner == null)
            inner = new Inner();
        return inner;
    }
      
    class Inner {//内部类
        public Inner() {
             
        }
    }
}

内部类可以拥有private访问权限、protect、publice以及包访问权限。

2.局部内部类(方法内部类)

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

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部内部类
            int age =0;
        }
        return new Woman();
    }
}

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

3.匿名内部类

匿名内部类应该是平时我们编写代码是用的最多的,你可以在定义一个类的同时对其进行实例化。

匿名内部类就是一个没有名字的方法内部类,

  • 匿名内部类必须继承一个抽象类或则实现一个接口。
  • 匿名内部类内没有类名,因此没有构造方法
  • 匿名内部类中不存在任何的静态成员变量和静态方法。
  • 匿名内部类为局部内部类,所以内部类所有的限制同样对匿名内部类有效。
  • 匿名内部类不能是抽象的,他必须实现继承的类或者接口的所有抽象方法。

创建格式:

new 父类构造器(参数列表)|实现接口()  
    {  
     //匿名内部类的类体部分  
    }

实例:

public abstract class Bird { //一个抽象的父类
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public abstract int fly(); //抽象类只有方法签名,没有方法体
}

public class Test {
    
    public void show(Bird bird){
        System.out.println(bird.getName() + "能够飞 " + bird.fly() + "米");
    }
    
    public static void main(String[] args) {
        Test test = new Test();//new一个Test类的对象.调用他的show方法
        test.show(new Bird() {
            
            public int fly() {
                return 10000;
            }
            
            public String getName() {
                return "大雁";
            }
        });
    }
}
------------------
Output:
大雁能够飞 10000米

在Test类中,test()方法接受一个Bird类型的参数。同时我们知道一个抽象类是没有办法直接new实例的,我们必须要先有实现类才能new一个他的实现类实例。所以main方法中直接使用匿名内部类来创建一个Bird实例。由于匿名内部类不是抽象类。所以他必须要实现他的抽象父类或者接口里面的所有抽象方法。

//匿名内部类的完全形式
public class WildGoose extends Bird{//继承抽象父类
    public int fly() {
        return 10000;
    }              //实现它的所有方法
    
    public String getName() {
        return "大雁";
    }
}

WildGoose wildGoose = new WildGoose(); //new实例对象
test.show(wildGoose);//通过test调用show方法

这里idea会创建一个继承自Bird类的匿名对象,该对象转型为Bird类型的引用。

匿名内部类的缺陷:仅能使用一次,创建匿名内部类时会创建一个该类的实例,该类的定义会立即消失,所以匿名内部类时不能被重复创建。

匿名内部类的初始化

前面说过匿名构造类没有类名,也就没有构造方法,正常来说我们都是通过构造器(构造方法)来完成初始化工作的!那么匿名类怎样初始化呢? 使用构造代码块!

public class OutClass {
    public InnerClass getInnerClass(final int age,final String name){//一个方法
         return new InnerClass() { //匿名内部类
            int age_ ;
            String name_;
            //构造代码块完成初始化工作
            {
                if(0 < age && age < 200){
                    age_ = age;
                    name_ = name;
                }
            }
          
            public String getName() {
                return name_;
            
            }
           
            public int getAge() {
                return age_;
            }
        };
      
    }
    
    public static void main(String[] args) {
        OutClass out = new OutClass();
        
        InnerClass inner_1 = out.getInnerClass(201, "chenssy");
        System.out.println(inner_1.getName());
        
        InnerClass inner_2 = out.getInnerClass(23, "chenssy");
        System.out.println(inner_2.getName());
    }
}

静态内部类

静态内部类同样是定义在类的内部,但是前面多了一个static关键字。静态内部类是不需要依附于外部类的,这点和类的静态成员有点类似,并且他不能使用外部的非static成员变量和方法,因为在没有外部类的情况下,可以创建一个静态内部类对象。

public class Test {
    public static void main(String[] args)  {
        Outter.Inner inner = new Outter.Inner(); //不需要依附于外部类的,可以直接创建一个静态内部类对象
    }
}
 
class Outter {
    public Outter() {
         
    }
     
    static class Inner {
        public Inner() {
             
        }
    }
}

Java内部类

原文:https://www.cnblogs.com/yppaopao/p/14038425.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!