JAVA面向对象学习——java面向对象概念———内部类

                                                      内部类

Java从JDK 1.1开始引入内部类,内部类主要有如下作用:

➢ 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。

➢ 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。

     但外部类不能访问内部类的实现细节,例如内部类的成员变量。

➢ 匿名内部类适合用于创建那些仅需要一次使用的类。

从语法角度来看,定义内部类与定义外部类的语法大致相同,内部类除需要定义在其他类里面之外,还存在如下两点区别:

➢ 内部类比外部类可以多使用三个修饰符:private、protected、static—外部类不可以使用这三个修饰符。

➢ 非静态内部类不能拥有静态成员。

-----------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------

public class Cow
{
	private double weight;
	
	public Cow()                  // 外部类的两个重载的构造器
	{
		
	}
	
	public Cow(double weight)
	{
		this.weight = weight;
	}
	
	
	private class CowLeg                 // 定义一个非静态内部类
	{
		
		private double length;               // 非静态内部类的两个实例变量
		private String color;
		
		public CowLeg()                   // 非静态内部类的两个重载的构造器
		{
			
		}
		
		public CowLeg(double length, String color)
		{
			this.length = length;
			this.color = color;
		}
		
		public void setLength(double length)    // 下面省略length、color的setter和getter方法
		{
			this.length = length;
		}
		
		ublic double getLength()
		{
			return this.length;
		}
		
		public void setColor(String color)
		{
			this.color = color;
		}
		
		public String getColor()
		{
			return this.color;
		}
		
		public void info()   // 非静态内部类的实例方法
		{
			System.out.println("当前牛腿颜色是:" + color + ", 高:" + length);
			
			System.out.println("本牛腿所在奶牛重:" + weight);    // 直接访问外部类的private修饰的成员变量
		}
	}
	
	public void test()
	{
		CowLeg cl = new CowLeg(1.12, "黑白相间");
		cl.info();
	}
	
	public static void main(String[] args)
	{
		Cow cow = new Cow(378.9);
		cow.test();
	}
}

public class Cow
{
    private double weight;

    public Cow()
    {

    }

    public Cow(double weight)
    {
        this.weight = weight;
    }


    private class CowLeg
    {

        private double length;
        private String color;

        public CowLeg()
        {

        }

        public CowLeg(double length, String color)
        {
            this.length = length;
            this.color = color;
        }

        public void setLength(double length)
        {
            this.length = length;
        }

        public double getLength()
       {
        return this.length;
        }

        public void setColor(String color)
        {
            this.color = color;
        }

        public String getColor()
        {
            return this.color;
        }

        public void info()
        {
            System.out.println(color + "----------" + length);

            System.out.println(weight);
        }
    }

    public void test()
    {
        CowLeg cl = new CowLeg(1.12, "黑白相间");
        cl.info();
    }

    public static void main(String[] args)
    {
        Cow cow = new Cow(378.9);
        cow.test();
    }
}

------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;


如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;


如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;


如果依然不存在,系统将出现编译错误:提示找不到该变量。


因此,如果外部类成员变量、内部类成员变量与内部类里方法的局部变量同名,则可通过使用 this、外部类类名.this 作为限定来区分。

如下程序所示。

public class DiscernVariable
{
	private String prop = "外部类的实例变量";
	
	private class InClass
	{
		private String prop = "内部类的实例变量";
public void info() { var prop = "局部变量"; System.out.println("外部类的实例变量值:" + DiscernVariable.this.prop); // 通过 外部类类名.this.varName 访问外部类实例变量 System.out.println("内部类的实例变量值:" + this.prop); // 通过 this.varName 访问内部类实例的变量 System.out.println("局部变量的值:" + prop); // 直接访问局部变量 } } public void test() { InClass in = new InClass(); in.info(); } public static void main(String[] args) { new DiscernVariable().test(); } }

执行结果:

------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------

6.7.1 非静态内部类
内部类都被作为成员内部类定义,而不是作为局部内部类。成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。

成员内部类分为两种:静态内部类和非静态内部类,使用static修饰的成员内部类是静态内部类,没有使用static修饰的成员内部类是非静态内部类。

成员内部类(包括静态内部类、非静态内部类)的class文件总是这种形式:OuterClass$InnerClass.class。

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在就使用该变量;如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量;如果依然不存在,系统将出现编译错误:提示找不到该变量。因此,如果外部类成员变量、内部类成员变量与内部类里方法的局部变量同名,则可通过使用this、外部类类名.this作为限定来区分。

非静态内部类的成员可以访问外部类的实例成员,但反过来就不成立了。如果外部类需要访问非静态内部类的实例成员,则必须显式创建非静态内部类对象来调用访问其实例成员。

根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。总之,不允许在外部类的静态成员中直接使用非静态内部类。

Java不允许在非静态内部类里定义静态成员,非静态内部类里不能有静态方法、静态成员变量、静态初始化块。

6.7.2 静态内部类
静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员,只能访问外部类的静态成员。

6.7.3 使用内部类
1.在外部类内部使用内部类

从前面程序中可以看出,在外部类内部使用内部类时,与平常使用普通类没有太大的区别。一样可以直接通过内部类类名来定义变量,通过new调用内部类构造器来创建实例。唯一存在的一个区别是:不要在外部类的静态成员(包括静态方法和静态初始化块)中使用非静态内部类,因为静态成员不能访问非静态成员。在外部类内部定义内部类的子类与平常定义子类也没有太大的区别。

2.在外部类以外使用非静态内部类

如果希望在外部类以外的地方访问内部类(包括静态和非静态两种),则内部类不能使用private访问控制权限,private修饰的内部类只能在外部类内部使用。

对于使用其他访问控制符修饰的内部类,则能在访问控制符对应的访问权限内使用:

➢ 省略访问控制符的内部类,只能被与外部类处于同一个包中的其他类所访问。

➢ 使用protected修饰的内部类,可被与外部类处于同一个包中的其他类和外部类的子类所访问。

➢ 使用public修饰的内部类,可以在任何地方被访问。

在外部类以外的地方定义内部类(包括静态和非静态两种)变量的语法格式如下:

由于非静态内部类的对象必须寄生在外部类的对象里,因此创建非静态内部类对象之前,必须先创建其外部类对象。在外部类以外的地方创建非静态内部类实例的语法如下:

3.在外部类以外使用静态内部类

因为静态内部类是外部类类相关的,因此创建静态内部类对象时无须创建外部类对象。在外部类以外的地方创建静态内部类实例的语法如下:

6.7.4 局部内部类
如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。由于局部内部类不能在外部类的方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。

6.7.5 匿名内部类
匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的格式如下:

关于匿名内部类还有如下两条规则:

➢ 匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类。

➢ 匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值