`
cvics_ailk
  • 浏览: 10850 次
社区版块
存档分类
最新评论

java内部类的作用分析

    博客分类:
  • Java
 
阅读更多

          提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比。内部类从表面上看,就是在类中又定义了一个类(下文会看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦。学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地设计你的程序结构。

Java中的内部类共分为四种

  静态内部类    static inner class (also called nested class)

  成员内部类    member inner class

  局部内部类    local inner class

  匿名内部类    anonymous inner class

        注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。所以内部类的成员变量/方法名可以和外部类的相同。

内部类的作用:

    1、隐藏你不想让别人知道的操作,也即封装性。

    2、一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!

内部类的功能在于,每个内部类都能独立的继承一个接口的实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多重继承的解决方案变得完整,并且内部类允许继承多个非接口类型(类或抽象类)。通过内部类分别继承一个基类,外部类创建内部类的对象,并使用内部类的方法,变相地实现了多继承。

下面从以下几个方面来介绍:

public interface Contents {
 int value();
}
public interface Destination {
 String readLabel();
}
public class Goods {
 private class Content implements Contents {
  private int i = 11;
  public int value() {
   return i;
  }
 }
 protected class GDestination implements Destination {
  private String label;
  private GDestination(String whereTo) {
   label = whereTo;
  }
  public String readLabel() {
   return label;
  }
 }
 public Destination dest(String s) {
  return new GDestination(s);
 }
 public Contents cont() {
  return new Content();
 }
}
class TestGoods {
 public static void main(String[] args) {
  Goods p = new Goods();
  Contents c = p.cont();
  Destination d = p.dest("Beijing");
 }
}
        这个例子里类Content和GDestination被定义在了类Goods内部,并且分别有着protected和private修饰符来控制访问级别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实现了两个接口Content和Destination。在后面的main方法里,直接用 Contents c和Destination d进行操作,你甚至连这两个内部类的名字都没有看见!这样,内部类的第一个好处就体现出来了 隐藏你不想让别人知道的操作,也即封装性。
同时,我们也发现了在外部类作用范围之外得到内部类对象的第一个方法,那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢?当然有,其语法格式如下:
outerObject=new outerClass(Constructor Parameters);
outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);
注意在创建非静态内部类对象时,一定要先创建起相应的外部类对象。至于原因,也就引出了我们下一个话题 非静态内部类对象有着指向其外部类对象的引用,对刚才的例子稍作修改:
public class Goods {
	private int valueRate = 2;
	private class Content implements Contents {
		private int i = 11 * valueRate;
		public int value() {
			return i;
		}
	}
	protected class GDestination implements Destination {
		private String label;
		private GDestination(String whereTo) {
			label = whereTo;
		}
		public String readLabel() {
			return label;
		}
	}
	public Destination dest(String s) {
		return new GDestination(s);
	}
	public Contents cont() {
		return new Content();
	}
}
        在这里我们给Goods类增加了一个private成员变量valueRate,意义是货物的价值系数,在内部类Content的方法value()计算价值时把它乘上。我们发现,value()可以访问valueRate,这也是内部类的第二个好处 一个内部类对象可以访问创建它的外部类对象的内容,甚至包括私有变量!这是一个非常有用的特性,为我们在设计时提供了更多的思路和捷径。要想实现这个功能,内部类对象就必须有指向外部类对象的引用。Java编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。
有人会问,如果内部类里的一个成员变量与外部类的一个成员变量同名,也即外部类的同名成员变量被屏蔽了,怎么办?没事,Java里用如下格式表达外部类的引用:
outerClass.this
有了它,我们就不怕这种屏蔽的情况了。
public class OutClassTest {
    private int num ;
    public OutClassTest(){
  
    }
 
    public OutClassTest(int num){
        this.num = num;
    }
 
    private class Inner{
        public OutClassTest getTest2(){
            return OutClassTest.this;
        }
  
        public OutClassTest newTest2(){
            return new OutClassTest();
        }
    }
 
    public static void main(String [] args){
        OutClassTest outClass = new OutClassTest(5);
        OutClassTest.Inner innerClass = outClass.new Inner();
        OutClassTest test2 = innerClass.getTest2();
        OutClassTest test3 = innerClass.newTest2();
        System.out.println(test2.num);
        System.out.println(test3.num);
    }
}------输出-------------------
5
0
 
静态内部类
和普通的类一样,内部类也可以有静态的。不过和非静态内部类相比,区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套类很相像了,Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上,当然从设计的角度以及以它一些细节来讲还有区别。
除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。

  注意只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。

             生成静态内部类对象的方式为:

            OuterClass.InnerClass inner = new OuterClass.InnerClass();

局部内部类
是的,Java内部类也可以是局部的,它可以定义在一个方法甚至一个代码块之内。
 
public class Outer {
	private int s = 100;
	private int out_i = 1;
	public void f(final int k) {
		final int s = 200;
		int i = 1;
		final int j = 10;
		// 定义在方法内部
		class Inner {
			int s = 300;// 可以定义与外部类同名的变量
			// static int m = 20;//不可以定义静态变量
			Inner(int k) {
				inner_f(k);
			}
			int inner_i = 100;
			void inner_f(int k) {
				// 如果内部类没有与外部类同名的变量,在内部类中可以直接访问外部类的实例变量
				System.out.println(out_i);
				// 可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的
				System.out.println(j);
				// 如果内部类中有与外部类同名的变量,直接用变量名访问的是内部类的变量
				System.out.println(s);
				// 用this.变量名访问的也是内部类变量
				System.out.println(this.s);
				// 用外部类名.this.内部类变量名访问的是外部类变量
				System.out.println(Outer.this.s);
			}
		}
		new Inner(k);
	}
	public static void main(String[] args) {
		// 访问局部内部类必须先有外部类对象
		Outer out = new Outer();
		out.f(3);
	}
}
 
        与局部变量类似,局部内部类前面是不可以加权限控制符的,也不能用static修饰。但是可以用final修饰,用来确保这个变量的值不会发生改变。所以如果局部类要访问带修饰的局部变量,只能访问用final修饰的局部变量。但是局部类可以访问外部类的所有成员,包括成员变量。
匿名内部类
java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一样,当你只需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的:
new interfacename(){......}; 或 new superclassname(){......};
下面接着前面继续举例子:
public class Goods3 {
	public Contents cont() {
		return new Contents() {
			private int i = 11;
			public int value() {
				return i;
			}
		};
	}
}
 
       这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象,看上去的确十分简洁。
在java的事件处理的匿名适配器中,匿名内部类被大量的使用。例如在想关闭窗口时加上这样一句代码:
frame.addWindowListener(new WindowAdapter(){
	public void windowClosing(WindowEvent e){
	   System.exit(0);
	}
}); 
        有一点需要注意的是,匿名内部类由于没有名字,所以它没有构造函数(但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类,创建它的时候必须带上这些参数,并在实现的过程中使用super关键字调用相应的内容)。如果你想要初始化它的成员变量,有下面几种方法:
如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为final。
将匿名内部类改造成有名字的局部内部类,这样它就可以拥有构造函数了。
在这个匿名内部类中使用初始化代码块。
为什么需要内部类?
java内部类有什么好处?为什么需要内部类?
首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时候,你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的,所以这样做可以完成所有你直接实现这个接口的功能。
不过你可能要质疑,更改一下方法的不就行了吗?
的确,以此作为设计内部类的理由,实在没有说服力。
真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题 没有多继承。实际上,C++的多继承设计起来很复杂,而java通过内部类加上接口,可以很好的实现多继承的效果。
分享到:
评论

相关推荐

    Java内部类继承问题的分析.pdf

    Java内部类继承问题的分析主要关注的是在Java编程中,当内部类(也称为嵌套类)参与继承时所面临的挑战和潜在问题。Java语言采用了单一继承机制,即一个类只能从一个父类继承,这有助于提高代码的可读性和可维护性。...

    浅谈Java内部类的四个应用场景

    通过本文,我们将深入探讨Java内部类的四个典型应用场景,并对每个场景进行详细分析,帮助初学者更好地理解并运用这一特性。 #### 二、Java内部类简介 Java中的内部类分为静态内部类(Static Inner Class)和非...

    Java 内部类的实现

    本文将通过分析给定的示例代码来深入了解Java内部类的实现方式。 #### 内部类概述 内部类可以分为以下几种类型: - **成员内部类**:作为外部类的一个成员,类似于属性或方法。 - **局部内部类**:在方法、构造器...

    java 利用反射获取内部类静态成员变量的值操作.docx

    ### Java 利用反射获取内部类静态成员变量的值操作 #### 一、引言 在Java编程中,反射是一个非常强大的工具,它允许程序在运行时检查类、接口、字段和方法的信息,并且能够创建和操作对象。本文将详细介绍如何使用...

    基于Java的匿名内部类分析与应用.pdf

    "基于Java的匿名内部类分析与应用" 匿名内部类是Java语言中的一大特色,它可以在类的定义中嵌套定义另一个类。匿名内部类没有名字,所以不能用匿名类声明对象,但是可以直接用匿名类创建一个对象。 匿名内部类的...

    基于java内部类作用的深入分析

    本篇文章将深入探讨Java内部类的作用,包括其分类、访问权限、以及如何创建和使用。 首先,Java内部类分为四种类型:成员内部类、局部内部类、匿名内部类和静态内部类。成员内部类类似于类的成员变量,可以在类的...

    java内部类的使用

    ### Java内部类的使用 #### 一、内部类的基本概念 内部类是在另一个类的内部定义的类。根据定义的位置不同,内部类可以分为几种不同的类型:成员内部类、局部内部类、静态内部类和匿名内部类。这里我们主要讨论的...

    详细分析Java内部类——局部内部类

    Java内部类之局部内部类 Java内部类是一种特殊的类,它可以嵌套在其他类中,今天我们主要介绍Java局部内部类的相关知识,了解局部内部类的定义、特性和使用场景。 什么是局部内部类? 局部内部类是定义在代码块、...

    C++内部类详细分析

    ### C++内部类详细分析 #### 一、引言 面向对象编程(OOP)自诞生以来,便成为了软件工程领域的重要组成部分。C++作为一种广泛使用的编程语言,支持面向对象编程特性,包括多重继承。多重继承是指一个类可以从多个...

    javacore和dump分析工具

    这个文件最重要的作用就是分析 Java 堆内存泄露问题,heap analyzer,MAT 等工具都可以分析这种文件。 Java core 文件保存的是 java 应用程序在崩溃时或任一时刻关于 Java 运行环境的各种信息。包括 Java 虚拟机的...

    java类修饰词和内部类详解

    ### Java 类修饰词详解 Java 作为一种广泛使用的面向...综上所述,Java 中的类修饰词和内部类在设计和实现面向对象程序时起着至关重要的作用。正确理解和使用这些概念可以帮助开发者构建更加灵活和可维护的软件系统。

    Java内部类详解

    本文将对Java内部类进行详细解读,分析其分类、特点以及在编程中的应用和注意点。 首先,内部类可以被分为几种不同的类型,每种类型都有其特定的应用场景和特点。从功能上来讲,内部类可以访问外部类的所有成员变量...

    Java匿名类的分析和理解.pdf

    Java匿名类的分析和理解 Java匿名类是Java编程语言中的一种特殊的类,它没有明确的类名。匿名类经常被用在Java GUI程序设计中,例如在Swing库中,以便快速地创建GUI组件。然而,很多Java学习者对匿名类的理解不够...

    java8 探讨与分析匿名内部类、lambda表达式、方法引用的底层实现的测试用例

    在Java 8中,匿名内部类、Lambda表达式和方法引用是重要的新特性,它们极大地简化了代码,提升了代码的可读性和效率。下面将详细探讨这三个知识点,并结合提供的测试用例进行分析。 1. **匿名内部类**: 匿名内部类...

    java期末复习抽象类与接口,内部类,知识点.zip

    复习时,可以详细阅读`Java抽象类.docx`来理解抽象类的定义、用途和实例化规则,通过`Java接口.docx`学习接口的定义、实现方式以及多继承的特点,`Java内部类.docx`将帮助你掌握不同类型的内部类及其应用场景。...

    Java匿名类,匿名内部类实例分析

    Java匿名类和匿名内部类实例分析 Java中的匿名类和匿名内部类是一种特殊的类,它们没有明确的名称,但它们可以继承父类的方法,访问外部类的成员变量和方法,并且可以重写父类的方法。下面将对Java中的匿名类和匿名...

    java线程内部类练习.rar

    通过学习和分析这些代码,我们可以更好地理解和掌握如何在实际项目中利用内部类来创建和控制线程,以及如何处理线程间的同步和通信问题,如使用synchronized关键字、wait()、notify()和notifyAll()等。 总的来说,...

    java学习笔记(内部类)汇集

    #### 四、内部类示例分析 接下来,我们将通过一个具体的例子来理解如何使用内部类以及它们与普通类的区别。 ##### 普通类实现示例 ```java public class TimerTest { public static void main(String[] args) { ...

    Java内部类应用之静态内部类应用示例

    Java内部类应用之静态内部类应用示例主要介绍了Java内部类应用之静态内部类应用,结合实例形式分析了Java静态内部类的原理、功能、用法及相关操作注意事项。 一、静态内部类的定义和特点 静态内部类是使用static...

    javacore分析工具

    JavaCore分析工具是一种在Java应用程序出现问题时,...总之,JavaCore分析工具是Java开发和运维过程中不可或缺的诊断工具,它能够帮助开发者深入理解JVM内部工作原理,有效地解决性能问题,保障Web应用程序的稳定运行。

Global site tag (gtag.js) - Google Analytics