关于Java中内部类的一些概念整理

把一个类放到另一个类的内部定义,这个定义在其他类内部的类就被称为内部类。

内部类的作用:

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

(2).内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节。

(3).匿名内部类适用于创建那些仅需要一次使用的类。

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

(5).非静态内部类不能拥有静态成员。

1.非静态内部类

定义内部类非常简单,只要把一个类放在另一个类内部定义即可。此处的“类内部”包括类中的任何位置,甚至在方法中也可以定义内部类(方法里定义的内部类被称为局部内部类)。

成员内部类是一种与成员变量、方法、构造器和初始化块相似的类成员;局部内部类和匿名内部类则不是类成员。

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

因为内部类作为其外部类的成员,所以可以使用任意访问控制符如private、protected和public等修饰。

外部类的上一级程序单元是包,所以他只有两个作用域:同一包内和任何位置。而内部类的上一级程序单元是外部类,它就具有4个作用域:同一个类、同一个包、父子类和任何位置,因此可以使用四中访问控制权限。

public class Cow {
	private double weight;
	//外部类的两个重载的构造器
	public Cow(){}
	public Cow(double weight){
		this.weight=weight;
	}
	//定义一个非静态内部类
	@SuppressWarnings("unused")
	private class CowLeg{
		//非静态内部类的两个实例变量
		private double length;
		private String color;
		//非静态内部类的两个重载的构造器
		public CowLeg(){}
		public CowLeg(double length,String color){
			this.length=length;
			this.color=color;
		}
		public double getLength() {
			return length;
		}
		public void setLength(double length) {
			this.length = length;
		}
		public String getColor() {
			return color;

		}
		public void setColor(String color) {
			this.color = color;
		}
		//非静态内部类的实例方法
		public void info(){
			System.out.println("当前牛腿颜色是:"+color+",高:"+length);
			//访问外部类的private修饰的成员变量
			System.out.println("本牛腿所在奶牛重:"+weight);
		}
	}
	public void test(){
		CowLeg c1=new CowLeg(1.12,"黑白相间");
		c1.info();
	}
	public static void main(String[] args) {
		Cow cow=new Cow(378.9);
		cow.test();
		/*
		 * 输出结果:
		 * 当前牛腿颜色是:黑白相间,高:1.12
                 * 本牛腿所在奶牛重:378.9
		 */
	}
}

上面程序在编译后生成两个class文件,一个是Cow.class,另一个是Cow$CowLeg.class,前者是外部类Cow的class文件,后者是内部类CowLeg的class文件,即成员内部类(包括静态内部类、非静态内部类)的class文件总是这种形式:OuterClass$InnerClass.class。

在非静态内部类对象里,保存了一个它所寄生的外部类对象的引用(当调用非静态内部类的实例方法时,必须有一个非静态内部类实例,非静态内部类实例必须寄生在外部类实例中)。

当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是够存在该名字的局部变量,如果存在就是用该变量;如果不存在,则到该方法所在的内部类中查找是否存在该名字的成员变量,如果存在就是用该成员变量;如果不存在,则到该内部类所在的外部类中查找是否存在该名字的成员变量,如果存在则使用该成员变量,如果已然不存在,系统将出现编译错误:提示找不到该变量。

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

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

通过OuterClass.this.propName的形式访问外部类的实例变量,通过this.propName的形式访问非静态内部类的实例变量。

非静态内部类的成员可以访问外部类的private成员,但反过来不成立。非静态内部类的成员只在非静态内部类范围内是可知的,并不能被外部类直接使用。如果外部类需要访问非静态内部类的成员,则必须显式创建非静态内部类对象来调用访问其实例成员。

public class Outer {
	private int outProp=9;
	class Inner{
		private int inProp=5;
		public void acessOuterProp(){
			//非静态内部类可以直接访问外部类的private成员变量
			System.out.println("外部类的outProp值:"+outProp);
		}
	}
	public void accessInnerProp(){
		//外部类不能直接访问非静态内部类的实例变量
		//下面代码编译错误
		//System.out.println("内部类的inProp值:"+inProp);
		//如需访问内部类的实例变量,必须显式创建内部类对象
		System.out.println("内部类的inProp值:"+new Inner().inProp);
	}
	public static void main(String[] args) {
		Outer out=new Outer();
		out.accessInnerProp();
		/*
		 * 输出结果:
		 * 内部类的inProp值:5
		 */
	}
}

非静态内部类对象和外部类对象的关系:非静态内部类对象必须寄生在外部类对象里,而外部类对象则不必一定有非静态内部类对象寄生其中。简单地说,如果存在一个非静态内部类对象,则一定存在一个被它寄生的外部类对象那个。但外部类对象存在时,外部类对象里不一定寄生非静态内部类对象。因此外部类对象访问非静态内部类成员时,可能非静态普通内部类对象根本不存在。而非静态内部类对象访问外部类成员时,外部类对象一定存在。

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

Java不允许在非静态内部类中定义静态变量。

非静态内部类中不能有静态方法、静态成员变量、静态初始化块。

非静态内部类中不可以有静态初始化块,但可以包含普通初始化块。非静态被不累普通初始化块的作用于外部类的初始化块作用完全相同。

2.静态内部类

如果使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象。因此使用static修饰的内部类被称为类内部类,有的地方也成为静态内部类。

static关键字的作用是把类的成员变成类相关,即static修饰的成员属于整个类,而不属于单个对象。外部类的上一级程序单元是包,所以不可使用static修饰;而内部类的上一级程序单元是外部类,使用static修饰可以将内部类变成外部类相关,而不是外部类实例相关,因此static关键字不可修饰外部类,但可修饰内部类。

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

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

静态内部类是外部类的一个静态成员,因此外部类的所有方法、所有初始化块中可以使用静态内部类来定义变量、创建对象等。

外部类依然不能直接访问静态内部类的成员,但可以使用静态内部类的类名来作为调用者来访问静态内部类的类成员,也可以使用静态内部类对象作为调用者来访问静态内部类的实例成员。

public class AccessStaticInnerClass {
	static class StaticInnerClass{
		private static int prop1=5;
		private int prop2=9;
	}
	public void accessInnerProp(){
		//System.out.println(prop1);
		//上面代码出现错误,应改为如下形式
		//通过类名访问静态内部类的类成员
		System.out.println(StaticInnerClass.prop1);
		//System.out.println(prop2);
		//上面代码出现错误,应该为如下形式
		//通过实例访问静态内部类的实例成员
		System.out.println(new StaticInnerClass().prop2);
	}
}

Java还允许在接口里定义内部类,接口里定义的内部类默认使用public static修饰——接口内部类只能是静态内部类。

如果为接口内部类指定访问控制符,则只能指定public访问控制符;如果定义接口内部类暂时省略访问控制符,则该内部类默认是public访问控制权限。

时间: 2024-11-08 04:32:41

关于Java中内部类的一些概念整理的相关文章

java中内部类的创建四种情况,三种方式,及内部数据访问权限

内部类和外部类的关系,及内部静态类的数据访问权限,声明方式. 第一种,在外部类内部声明使用内部类,内部类的类型为static和非 static类型,内部类数据类型为private,protected,public 类型的访问权限.外部类为非静态声明和权限如下: package com; public class Test1 { //@author 张春蕾 private class Name{ private int i =1; public int s = 2; protected int m

Java中内部类

内部类的规则: 1.内部类可以直接访问外部类中的成员,包括私有. 之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 访问格式: 1.当内部类定义在外部类的成员位置了,而且非私有,可以在外部其他类中. 可以直接建立内部类对象. 格式: 外部类类名.内部类名  变量名= new 外部类对象.new 内部类对象. Outer.inner out = new Outer().new inner(); 2.当内部类在

Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“

声明:本博客为原创博客,未经允许,不得转载!原文链接为 http://blog.csdn.net/bettarwang/article/details/27012421. 我们都知道,非静态内部类可以访问外部类的私有成员(包括私有变量和方法),这也正是使用非静态内部类与普通类的一个重要区别:非静态内部类是依赖于外部类对象而存在的,这种依赖就包括它要能自由地访问外部类对象的所有成员(因为private成员都可以访问了,其他权限的成员更不在话下.不过一般来说一个内部类只会访问外部类的部分成员而不是全

java中内部类的讲解

java中有一个内部类的概念,由于之前一直比较忙,没有单独拿出时间总结一下,今天我就把内部类的相关知识进行一下汇总,如果有不足之处,欢迎批评指正. 1)java内部类的概念.       在一个类的的内部定义的类被称为java的内部类 2)内部类的分类      根据内部类的位置不同,可以大致分为一下两类: 1.普通内部类又叫成员内部类,在方法体的外面定义的内部类 其中普通内部类又分为静态(static修饰的内部类)和非静态(非static修饰的内部类) 2.局部内部类又叫方法内部类,在方法体中

java中内部类的积累

放在一个类的内部的类我们就叫内部类. 二. 作用 1.内部类可以很好的实现隐藏 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以 2.内部类拥有外围类的所有元素的访问权限 3.可是实现多重继承 4.可以避免修改接口而实现同一个类中两种同名方法的调用. 提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就是在类中又定

[转]java中的字符串相关知识整理

字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果写过C/C++的应该就了解,在字符串的操作上会有许多操作的函数与类,用于简化代码的开发.一方面是因为字符串在代码中会频繁用到,另一方面是因为字符串的操作非常麻烦. 最初我知道String的特殊待遇就是在delphi中,因为String在delphi里是一个关键字存在,与其他的基本类型是不一样的.那时

JAVA中内部类(匿名内部类)访问的局部变量为什么要用final修饰?

本文主要记录:在JAVA中,(局部)内部类访问某个局部变量,为什么这个局部变量一定需要用final 关键字修饰? 首先,什么是局部变量?这里的局部是:在方法里面定义的变量. 因此,内部类能够访问某局部变量,说明这个内部类不是在类中定义的内部类,而是在方法中定义的内部类,称之为:局部内部类. 局部变量的作用域:局部变量是在某个方法中定义,当该方法执行完成后,局部变量也就消失了.[局部变量分配在JVM的虚拟机栈中,这部分内存空间随着程序的执行自动回收],也即:局部变量的作用域是在 “方法的范围内”.

Java中的异常处理从概念到实例

1.概念 采用新的异常处理机制 在以往的程序开发过程中,经常采用返回值进行处理.例如,在编写一个方法,可以返回一个状态代码,调用者根据状态代码判定出错与否.若状态代码表示一个错误,则调用这进行相应的处理,或显示一个错误页面或错误信息.通过返回值进行处理的方法是有效的,但是有它的许多不足之处. 1. 程序复杂 2. 可靠性差 3. 返回信息有限 4. 返回代码标准化困难 采用错误代码和异常处理相结合的方式的优越性: 1. 把错误代码与常规代码分开 2. 可以在catch中传播错误信息 3. 可以对

java中线程锁的概念

java多线程:锁 java的多线程中的锁是干嘛的呢?在网上找了很多博客,大都是很专业的语言,让我一时间摸不着头脑.下面分三个部分来总结多线程中的锁的概念. 一,基础概念: 多线程在运行的时候可能会遇到这样的问题,多个线程要用到同一个资源,那么可能会出现错乱,比如线程要改动资源里的数据,那么多个线程同时改就乱了套了.就像公共厕所,必须要一个一个接着上,不能两个人或者多个人同时上.那么锁这个东西就是像厕所里的门,一个人在上厕所,锁上了们,那下一个人就不能进去了.同样的,如果我们想让某一个程序或者某