黑马程序员——————>非静态内部类

------- android培训、java培训、期待与您交流! ----------

大部分时候,类被定义成一个独立的程序单元。在某些情况下,也会把一个类放在另一个人类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类,内部类主要有如下作用:

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

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

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

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

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

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

非静态内部类

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

大部分时候,内部类都被作为成员内部类定义,而不是作为局部内部类。成员内部类是一种与成员变量,方法,构造器和初始化块相似的类成员:局部内部类和匿名内部类则不是类成员。

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

下面程序在Cow类里定义了一个CowLeg非静态内部类,并在CowLeg类的实例方法中直接访问Cow的private访问权限的实例变量。

 1 public class Cow
 2 {
 3     private double weight;
 4
 5     //外部类的两个重载的构造器
 6     public Cow(){}
 7     public Cow(double weight)
 8     {
 9         this.weight = weight;
10     }
11
12     //定义一个非静态内部类
13     private class CowLeg
14     {
15         //非静态内部类的两个实例变量
16         private double length;
17         private String color;
18         //非静态内部类的两个重载的构造器
19         public CowLeg(){}
20         public CowLeg(double length, String color)
21         {
22             this.length = length;
23             this.color = color;
24         }
25
26         //省略set和get方法
27
28
29         //非静态内部类的实例方法
30         public void info()
31         {
32             System.out.println("当前牛腿的颜色是:" + color + ", 高: " +length);
33
34             //直接访问外部类的private修饰的成员变量
35             System.out.println("本牛腿所在的奶牛重:" + weight);
36         }
37     }
38
39     public void test()
40     {
41         CowLeg c = new CowLeg(1.12, "黑白相间");
42         c.info();
43     }
44
45     public static void main(String[] args)
46     {
47         Cow cow = new Cow(378.9);
48         cow.test();
49     }
50 }

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

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

 1 public class DiscernVariable
 2 {
 3     private String prop = "外部类的实例变量";
 4
 5     private class InClass
 6     {
 7         private String prop = "内部类的实例变量";
 8
 9         public void info()
10         {
11             String prop = "局部变量";
12             //通过外部类类名.this.VarName访问外部类实例变量
13             System.out.println("外部类的实例变量值: " + DiscernVariable.this.prop);
14             //通过this.varName访问内部类实例的变量
15             System.out.println("内部类的实例变量值: " + this.prop);
16             //直接访问局部变量
17             System.out.println("局部变量的值: " + prop);
18         }
19     }
20     public void test()
21     {
22         InClass in = new InClass();
23         in.info();
24     }
25     public static void main(String[] args)
26     {
27 //        DiscernVariable dv = new DiscernVariable();
28 //        dv.test();
29         new DiscernVariable().test();
30     }
31 }

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

 1 public class Outer
 2 {
 3     private int outProp = 9;
 4
 5     class Inner
 6     {
 7         private int inProp = 5;
 8         public void acessOuterProp()
 9         {
10             //非静态内部类可以直接访问外部类的private成员变量
11             System.out.println("外部类的outProp值:" + outProp);
12         }
13     }
14     public void accessInnerProp()
15     {
16         //外部类不能直接访问非静态内部类的实例变量
17         //下面代码编译错误
18 //        System.out.println("内部类的值:" + inProp);
19
20         //如需访问内部类的实例变量,必须显式创建内部类对象
21         System.out.println("内部类的inProp值:" + new Inner().inProp);
22     }
23
24     public static void main(String[] args)
25     {
26         //执行下面代码,只创建了外部类对象,还未创建内部类对象
27         Outer out = new Outer();
28         out.accessInnerProp();
29     }
30 }

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

 1 public class StaticTest
 2 {
 3     //定义一个非静态的内部类,是一个空类
 4     private class In
 5     {
 6
 7     }
 8
 9     //外部类的静态方法
10     public static void main(String[] args)
11     {
12         //下面代码引发编译异常,因为静态成员main方法
13         //无法访问非静态成员In类
14
15         new In();
16     }
17 }

java不允许在非静态内部类里定义静态成员。

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

时间: 2024-12-23 09:33:38

黑马程序员——————>非静态内部类的相关文章

黑马程序员——java基础——内部类

 黑马程序员--java基础--内部类 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 内部类 如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象.这时,为了方便设计和访问,直接将A类定义在B类中.就可以了.A类就称为内部类.内部类可以直接访问外部类中的成员.而外部类想要访问内部类,必须要建立内部类的对象. 内部类的访问规则 1,内部类可以直接访问外部类中的成员,包括私有. 之所以可以直接访问外部类中的成员,是因为内部类中持有

黑马程序员-内部类、 抽象类、接口

java面向对象中比较重要的知识还有内部类,抽象类.接口,这些和封装.继承.多态一起赋予java强大的面向对象的能力 1.抽象类 在面向对象的领域一切都是对象,同时所有的对象都是通过类来描述的,但是并不是所有的类都是来描述对象的.如果一个类没有足够的信息来描述一个具体的对象,而需要其他具体的类来支撑它,那么这样的类我们称它为抽象类. 创建抽象类和抽象方法非常有用,因为他们可以使类的抽象性明确起来,并告诉用户和编译器打算怎样使用他们.抽象类还是有用的重构器,因为它们使我们可以很容易地将公共方法沿着

黑马程序员_Java抽象类和内部类

- - - - - android培训.java培训.期待与您交流! - - - - - - 类(class) 类是相似对象中共同属性和方法的集合体 在面向对象中定义类,就是在描述事物,就是在定义属性(变量)和行为(方法).属性和行为共同成为类中的成员(成员变量和成员方法). 封装.继承和多态 面向对象方法中软件设计的主体是类,类是相同属性和方法的封装体,因此类具有封装性 子类可以在继承父类所有属性和方法的基础上,再增加自己特有的属性和方法,因此类具有继承性 在一个类层次中,定义为根类的对象可被

黑马程序员_C语言总结-基础部分

C语言基础 1.C语言的关键字 1>关键字就是C语言提供的有特殊含义的符号,也称为保留字,C语言中一共有32个关键字,这些关键字都有自己的含义 例如:int double float if  else switch for 等等 2.标示符的概念: 1>标示符就是在程序中自定义的一些名称,比如函数名,变量名,结构体名等等这些都是标示符 2>命名规则: 1>只能由英文字母的大小写和数字以及_下划线组成,且首字母必须为字母或者下划线_ 2>在C语言中是严格区分大小写的,比如if是

黑马程序员_JAVA 基础加强学习笔记

一.面向对象 (一)继承  1.继承的好处: (1) 提高了代码的复用性. (2) 让类与类之间产生了关系,提供了另一个特征多态的前提. 注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();  如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数. 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数. 2.final特点

黑马程序员 ---------- Java网络技术之 ---正则表达式 (Day06)

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 正则表达式 正则表达式:基本知识 1  字符,   2 字符类 , 3 预定义字符类 , 4 边界匹配器 ,5 Greedy 数量词,6 Logical 运算符 详解: 1 字符 x   字符 x \\ 反斜线字符 \0n 带有八进制值 0 的字符 n (0 <= n <= 7) \0nn 带有八进制值 0 的字符 nn (0 <= n

黑马程序员——集合篇

------- android培训.java培训.期待与您交流! ---------- 1.集合类 为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一 种方式. 数组和集合类同是容器,有何不同? 数组虽然也可以存储对象,但长度是固定的:集合长度是可变的.数组中可以存储基本数据类型,集合只能存储对象. 集合类的特点 集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象. 2.集合框架的构成及分类 3.

黑马程序员_多线程

------- android培训.java培训.期待与您交流! ---------- 多线程1.进程: 正在运行的程序所占有的内存空间,叫做进程. 线程: 一个应用程序中的子程序,对于CPU,子程序可以有一条独立的执行路径,称为线程. 线程特点:依靠一个应用程序,对于其他子程序,独立被CPU执行的2.多线程的好处: 充分利用CPU的资源,程序的同时运行,提高效率3.java中线程创建的两种方法: 第一种: 定义类继承Thread class extends Thread 重写Thread中的r

【黑马程序员】————基本运算

一.  算术运算 C语言一共有34种运算符,包括了常见的加减乘除运算 1. 加法运算+ 除开能做加法运算,还能表示正号:+5.+90 2. 减法运算- 除开能做减法运算,还能表示符号:-10.-29 3. 乘法运算* 注意符号,不是x,而是* 4. 除法运算/ 注意符号,不是÷,也不是\,而是/ 整数除于整数,还是整数.1/2的值是0,这个并不是二分之一 5. 取余运算(模运算)% 什么是取余:两个整数相除之后的余数 %两侧只能是整数 正负性取决于%左侧的数值 6. 注意点 1>     自动类