网站首页 > 精选教程 正文
在Java系统中可以通过静态嵌套类与内部类的声明操作将嵌套结构导入类的设计之中,让具有相关功能的类相互配合,进而方便程序设计人员控制这些类的使用范围(作用域)。在Java类的声明中可以包含其他类声明的成员,这种概念称为嵌套类(Nested Class)。嵌套类分为两种:一种是非静态嵌套类(Non-Static Nested Class),也称为内部类。另一种是静态嵌套类(Static Nested Class),内部类被static修饰。另外,嵌套类还可以匿名。
内部类编译后的文件名为:“外部类名$内部类名.java”;
为什么内部类可以直接访问外部类中的成员呢?
那是因为内部中都持有一个外部类的引用。这个是引用是
外部类名.this
内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。
当内部类被定义在局部位置上,只能访问局部中被final修饰的局部变量。
如果内部类被静态修饰,相当于外部类,会出现访问局限性,只能访问外部类中的静态成员。如果内部类中定义了静态成员,那么该内部类必须是静态的。
1 内部类(非静态嵌套类)
如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,可以直接将A类定义在B类中,A类就称为内部类,B类称为外部类。内部类可以直接访问外部类中的成员,包括私有成员。而外部类想要访问内部类,必须要建立内部类的对象。
由于内部类与其他的实例类成员一样都附属于主类对象,因此可以直接存取对象的实例变量(Instance Variable)与实例方法(Instance Method),并且在内部类之中不得包含任何静态成员(Static Member)。
class Outer{
int num = 4;
class Inner {
void show(){
System.out.println("inner show run "+num); // 内部类访问外部类的成员
}
}
public void method(){
Inner in = new Inner(); // 创建内部类的对象。
in.show(); // 调用内部类的方法。
}
}
以下demo code在有嵌套的类中没有使用static关键字,正常:
class InnerClassDemo {
class Inner{
void show(){System.out.println("hi");}
}
public void method(){
this.new Inner().show();
}
}
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
InnerClassDemo ic = new InnerClassDemo();
ic.method(); // hi
}
}
以下在有嵌套的类中在静态方法中不允许使用this:
class InnerClassDemo {
class Inner{
void show(){}
}
public void method(){
this.new Inner().show(); //可以
}
public static void main(String[] args) { // static不允许this
this.new Inner().show(); // 错误,Inner类需要定义成static
}
}
如果有外部类在静态方法(如main()主执行区块)中创建内部类对象,就必须使用完整的类路径语句来指定该对象的引用位置,并在外部类中声明内部类的相关方法,该方法返回内部类创建对象的引用值:
class OuterClass{
// 主类构造函数
public OuterClass(){
System.out.println("主类构造函数的语句");
}
// 声明静态嵌套类
static class InnerClass{
public InnerClass(){
System.out.println("静态嵌套类构造函数的语句");
}
void show(){System.out.println("hi");}
}
// 主程序区块
public static void main(String args[]){
new OuterClass();
new InnerClass().show();
}
}
2 静态嵌套类
静态嵌套类不同于内部类,并不是依附于主类(外部类)创建的对象,而是直接附属于主类。因此,静态嵌套类无法直接存取实例变量或调用任何实例方法,只能通过对象来间接存取或调用类的实例成员。
另外,由于静态嵌套类属于主类的静态成员,因此可以不通过主类的成员方法来返回对象实现的引用值,即可以直接在主类的静态方法(例如main()主执行区块)中进行内部类对象的创建工作。
class InnerClassDemo {
static class Inner{
void show(){
System.out.println("hi");
}
}
public void method(){
new Inner().show();
}
public static void main(String[] args) {
new InnerClassDemo();
new Inner().show();//hi
}
}
3 匿名内部类
如果我们所声明的内部类或嵌套静态类必须继承某个类或实现某个接口,就可以在不定义类名称的情况下,直接通过基类或接口的构造函数引用值来创建该类的对象:
class Ideone
{
public static void main (String[] args)
{
Object obj = new Object(){
public String toString(){
return "这是一个内部的匿名类!";
}
};
}
}
这种不具有类名,但可以直接调用基类或接口的构造函数来创建派生类对象的类,我们称其为匿名类(Anonymous Class)或匿名内部类。匿名类的语法格式如下:
基类(接口)名称派生匿名类对象 = new 基类(接口)构造函数(){
// 声明匿名类成员的程序语句
}
// 或
new 父类名或接口名(){ 定义子类成员或者覆盖父类方法 }.方法;
匿名内部类是嵌套类的简化形式。一般只用一次就可以用这种形式。匿名内部类其实就是一个匿名子类对象。想要定义匿名内部类:内部类必须继承一个类或者实现接口。
new Object(){
void show(){
System.out.println("show run");
}
}.show();
以下是错误的示范:
Object obj = new Object(){
void show(){
System.out.println("show run");
}
};
obj.show();
编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,就被提升为了Object类型,而编译时检查Object类中是否有show方法,所以编译失败。
匿名类一般用于实现一个接口或继承一个特定的类:
interface Inter{
void show();
}
class Outer{//通过匿名内部类补足Outer类中的代码。
public static Inter method(){
return new Inter(){
public void show(){System.out.println("hi");}
};
}
}
class InnerClassDemo {
public static void main(String[] args) {
Outer.method().show(); // hi
/*
Outer.method():意思是:Outer中有一个名称为method的方法,而且这个方法是静态的。
Outer.method().show():当Outer类调用静态的method方法运算结束后的结果又调用了show方法,意味着:method()方法运算完一个是对象,而且这个对象是Inter类型的。
*/
function (new Inter(){
public void show(){System.out.println("hello");}
}); //匿名内部类作为方法的参数进行传递。
}
public static void function(Inter in){
in.show(); // hello
}
}
}
demo code 2:
class OuterClass{
//外部类构造函数
public OuterClass(){
System.out.println("成功实现外部类的构造函数!!!");
}
//声明内部类
class MyInnerClass{
//内部类的构造函数
public MyInnerClass(){
System.out.println(" 成功实现内部类的构造函数!!!");
}
public void show(){
System.out.println(" 成功调用内部类的show()方法!!!");
}
}
//声明并定义内部匿名类
public MyInnerClass MyInnerClass(){
//返回内部匿名类创建的方法
return new MyInnerClass(){
//覆盖(重新定义)内部类的成员方法
public void show(){
System.out.println(" 成功调用内部匿名类的show()方法!!!");
}
};
}
//主程序区块
public static void main(String args[]){
//创建主类对象
OuterClass myObject = new OuterClass();
//创建内部匿名类对象
MyInnerClass myAnonymous = myObject.MyInnerClass();
//调用内部匿名类覆盖(重新定义)的方法
myAnonymous.show();
}
}
/*output:
成功实现外部类的构造函数!!!
成功实现内部类的构造函数!!!
成功调用内部匿名类的show()方法!!!
*/
ref
赵军 吴灿铭《编程语言 Java程序设计与计算思维》
-End-
- 上一篇: 这些Java中的内部类你不应该知道吗?
- 下一篇: Java——内部类详解
猜你喜欢
- 2024-11-24 永远不要使用双花括号初始化实例,除非你想OOM
- 2024-11-24 java中的匿名内部类总结
- 2024-11-24 Java Nested Classes(内部类~英文技术文档翻译)
- 2024-11-24 带你深入学习java内部类_匿名类,细到不能再细
- 2024-11-24 为何要在Java中使用静态类?
- 2024-11-24 68、下面的内部类在哪里new不会编译出错
- 2024-11-24 面向对象高级特性内部类
- 2024-11-24 Java局部内部类
- 2024-11-24 Java 内部类和异常类(详细版)
- 2024-11-24 IntelliJ IDEA 2022.2.1 beta 发布,新增支持 Java 18
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)