`
DavyJones2010
  • 浏览: 154063 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java SE: Inner Class

阅读更多

1) Why would we use InnserClass?

    1> Inner class methods can access the data from the scope in which they are defined - including data that would otherwise be private.

    2> Inner classes can be hidden from other classes in the same package.

    3> Anonymous inner class are handy when you want to define callbacks without writing a lot of code.

 

Example for "InnerClass Access the Data Of OutterClass"

package edu.xmu.inner;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.Timer;

public class TalkingClock {
    private boolean shouldBeep;
    private int interval;

    public TalkingClock(boolean shouldBeep, int interval) {
	super();
	this.shouldBeep = shouldBeep;
	this.interval = interval;
    }

    public void start() {
	TimePrinter printer = new TimePrinter();
	Timer t = new Timer(interval, printer);
	t.start();
    }

    class TimePrinter implements ActionListener {
	@Override
	public void actionPerformed(ActionEvent e) {
	    Date date = new Date();
	    System.out.println("At the tone, the time is: " + date);
	    if (shouldBeep) { // Here inner get access to the property of outter
			      // class directly
		Toolkit.getDefaultToolkit().beep();
	    }
	}

	public int getInterval() {
	    return interval;
	}
    }

    public void test() {
	// Here we created an InnerClass without an instance of OutterClass
	// The reason is that the instance of OutterClass is "this" and don't
	// have to declare explicitly

	// TimePrinter printer = new TalkingClock.TimePrinter();
	// TimePrinter printer = this.new TimePrinter();
	TimePrinter printer = new TimePrinter();

	System.out.println(printer.getInterval());
    }
}

class AnotherClass {
    public void print() {
	TalkingClock clock = new TalkingClock(false, 1000);
	// InnerClass will not be created without OutterClass
	// If TimePrinter is private inner class, we cannot create it even with
	// instance of OutterClass
	TalkingClock.TimePrinter printer = clock.new TimePrinter();
	System.out.println(printer.getInterval());
    }
}

    Thus we can conclude that "InnerClass cannot exists/created without Instance of OutterClass".

    1> Only InnerClass can be private. Regular classes always have either package or public visibility.

 

Example for: "Local InnerClass"

package edu.xmu.inner;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.Timer;

public class TalkingClock {
    private boolean shouldBeep;
    private int interval;

    public TalkingClock(boolean shouldBeep, int interval) {
	super();
	this.shouldBeep = shouldBeep;
	this.interval = interval;
    }

    public void start() {
	class TimePrinter implements ActionListener {
	    @Override
	    public void actionPerformed(ActionEvent e) {
		Date date = new Date();
		System.out.println("At the tone, the time is: " + date);
		if (shouldBeep) {
		    Toolkit.getDefaultToolkit().beep();
		}
	    }
	}

	TimePrinter printer = new TimePrinter();
	Timer t = new Timer(interval, printer);
	t.start();
    }
}

    1) Local classes are never delcared with an access specifier(this is, public or private).

        Their scope is always restricted to the block(especially, method block) in which they are declared.

    2) Local classes have a great advantage: they are completely hidden from the outside world-not even other code in the TalkingClock class can access them.

        No method except start() has any knowledge of the TimePrinter class.

    3) However, those local variables must be declared final.

    public void start(final Date endDate) {
	class TimePrinter implements ActionListener {
	    @Override
	    public void actionPerformed(ActionEvent e) {
		Date date = new Date();
		if (date.before(endDate)) {
		    System.out.println("At the tone, the time is: " + date);
		    if (shouldBeep) {
			Toolkit.getDefaultToolkit().beep();
		    }
		}
	    }
	}
	TimePrinter printer = new TimePrinter();
	Timer t = new Timer(interval, printer);
	t.start();
    }

       Why should the variable endDate declared as final?

Step1> The start method is called.
Step2> The printer instance is initialized by a call to the constructor of InnerClass TimePrinter.
Step3> The printer instance is passed to the Timer constructor, the timer is started, and the start(Date) method exits.
At this point, the endDate parameter variable of the start(Date) method no longer exists.
Step4> 1000ms later, the actionPerformed method executes if(date.before(endDate))...

Thus, for the code in actionPerformed method to work, the TimerPrinter class must have copied the endDate field as a local variable of start method before the endDate field went away.

 

Example for "Anonymous Inner Class"

    public void start(final Date endDate) {
	Timer t = new Timer(interval, new ActionListener() {
	    @Override
	    public void actionPerformed(ActionEvent e) {
		Date date = new Date();
		if (date.before(endDate)) {
		    System.out.println("At the tone, the time is: " + date);
		    if (shouldBeep) {
			Toolkit.getDefaultToolkit().beep();
		    }
		}
	    }
	});
	t.start();
    }

2) Static Inner Class

    1> Occasionally, you want to use an inner class simply to hide one class inside another,

         but you don't need the inner class to have a reference to the instance of outer class.

         You can suppress the generation of that reference by declaring the inner class "static".

     2> Static Inner Class is also called Nested Class.

Example for "Static Inner Class":

    We need to get the max and min value in an array at the same time.

    If do not use Static Inner Class, we have to traverse the array twice.

package edu.xmu.inner;

public class InnerClassTest {
    public static void main(String[] args) {
	Calculator calculator = new Calculator();
	double[] values = { 1.1, 2.2, 3.3, 4.4, 0, -1.1, -2.2, -3.3, -4.4 };
	double max = calculator.getMax(values);
	double min = calculator.getMin(values);
	System.out.println("max = " + max + ", min = " + min);
    }
}

class Calculator {
    public double getMax(double[] values) {
	double max = Double.MIN_VALUE;
	for (double value : values) {
	    if (value > max) {
		max = value;
	    }
	}
	return max;
    }

    public double getMin(double[] values) {
	double min = Double.MAX_VALUE;
	for (double value : values) {
	    if (value < min) {
		min = value;
	    }
	}
	return min;
    }
}

    Use Static Inner Class:

package edu.xmu.inner;

import edu.xmu.inner.Calculator.Pair;

public class InnerClassTest {
    public static void main(String[] args) {
	Calculator calculator = new Calculator();
	double[] values = { 1.1, 2.2, 3.3, 4.4, 0, -1.1, -2.2, -3.3, -4.4 };
	Pair pair = calculator.getMaxAndMin(values);
	System.out.println("max = " + pair.getMax() + ", min = "
		+ pair.getMin());
    }
}

class Calculator {
    public Pair getMaxAndMin(double[] values) {
	double max = Double.MIN_VALUE;
	double min = Double.MAX_VALUE;

	for (double value : values) {
	    if (value < min) {
		min = value;
	    }
	    if (value > max) {
		max = value;
	    }
	}
	return new Pair(max, min);
    }

    static class Pair {
	double max;
	double min;

	public Pair(double max, double min) {
	    super();
	    this.max = max;
	    this.min = min;
	}

	public double getMax() {
	    return max;
	}

	public double getMin() {
	    return min;
	}
    }
}

    Benefits:

        1> The name Pair is an exceedingly common name.

             And in a large project, it is quite possible that other module has the same named class but for different purpose.

             We can solve this potential name clash by making Pair a public inner class inside Calculator.

             Then the class will be know to the public as Calculator.Pair

     Also, we can refer to Map.EntrySet<K, V> as a justification.

public class InnerClassTest {
    public static void main(String[] args) {
	Map<String, String> map = new HashMap<String, String>();
	map.put("A", "Hello");
	map.put("B", "Hallo");

	for (Map.Entry<String, String> entry : map.entrySet()) {
	    System.out.println(entry.getKey() + " = " + entry.getValue());
	}
    }
}
分享到:
评论

相关推荐

    JAVA的核心技术:面向对象编程

    6. 内部类(Inner Class):Java允许在一个类内部定义另一个类,这种类称为内部类。内部类可以访问外部类的所有成员,包括私有成员,这为代码组织和实现特定功能提供了便利。 7. 枚举(Enum):枚举是Java中的特殊...

    Java基础资料

    Day05可能涵盖了抽象类(Abstract Class)和内部类(Inner Class)的概念。 第三章:JAVA-SE-01 这部分可能是对Java Standard Edition(Java SE)更深入的学习,可能涉及到文件I/O、异常处理、集合框架、反射、线程...

    java.核心技术.第八版 卷1

    Volume I is designed to quickly bring you up to speed on what’s new in Java SE 6 and to help you make the transition as efficiently as possible, whether you’re upgrading from an earlier version of ...

    Java面试题

    - 内部类允许一个类的内部定义另一个类,StaticNestedClass和InnerClass的主要区别在于InnerClass可以访问外部类的实例变量和方法,而StaticNestedClass不可以。 8. Java异常处理知识点: - try块用于捕获异常,...

    CDA_JAVA:首演平均语言JAVA

    8. 内部类(Inner Class):Java允许在类内部定义其他类,这有助于封装和抽象,提高代码复用。 9. 泛型(Generics):泛型提供了一种在编译时检查类型安全的方法,同时减少了在代码中显式类型转换的需要。 10. ...

    java_词汇表速查手册

    6. **API(应用程序接口)**:一组预定义的类和方法,供开发者在开发应用时使用,如Java SE API、Java EE API等。 7. **数组 (Array)**:存储同类型数据的序列,可以通过索引访问。在Java中,数组是对象。 8. **...

    Java基础知识练习题

    - **问题解析**:Java 中有两种内部类:静态内部类(Static Nested Class)和非静态内部类(Inner Class)。 - **区别**: - **静态内部类**: - 可以拥有静态成员; - 不依赖于外部类的实例; - 访问权限同外部...

    JVM基础.doc

    - **JDK 1.0** (1997年):引入了AWT、InnerClass等重要特性。 - **J2SE 1.2** (2000年):引入HotSpot虚拟机。 - **J2SE 5.0** (2004年):引入了泛型、枚举等高级特性。 - **Java SE 6** (2006年):引入了NIO 2.0、...

    Java 编程思想源代码使用导入eclipse流程

    解压后的文件夹结构应包含多个子文件夹,比如`innerclass`、`initialization`等,这些都是源代码的组织方式。 2. **新建工程**:确保Java的开发环境已经配置好。在JAVASE 8及以上版本,需要配置JDK和JRE的环境变量...

    java中final类型等的应用

    final class InnerClass {} // 声明一个不可继承的内部类 final void method() {} // 声明一个不可重写的方法 } } ``` 以上就是从提供的文件信息中提取的主要知识点。这些知识点涵盖了Java中的字符编码(特别是...

    Java面试宝典2013版

    - `Inner Class`(成员内部类):需要通过外部类对象来访问。 #### 27. 内部类引用外部类成员的限制 - 内部类可以直接访问外部类的所有成员(包括私有的)。 - 内部类也可以访问外部类的静态成员。 #### 28. 匿名...

    Java中的内部类应用举例

    在Java编程语言中,内部类(Inner Classes)是一种独特的概念,它允许开发者在类的内部定义另一个类。这种设计模式增强了代码的封装性和模块化,同时也提供了更灵活的编程方式。根据其定义位置和修饰符的不同,内部...

    Java程序员面试题集常见题目经典精选汇总大全(1-50).docx

    11. 内部类(Inner Class) 内部类是定义在一个类内部的类,分为成员内部类、局部内部类、匿名内部类和静态内部类。 12. 泛型(Generics) 泛型是Java SE 5.0引入的新特性,用于在编译时检查类型安全,减少类型...

    OOPJ:“使用Java进行面向对象的编程入门”培训课程的材料

    12. 泛型(Generics): 泛型是Java SE 5.0引入的新特性,允许在类、接口和方法中使用类型参数,以提高代码的类型安全性和重用性。 13. 注解(Annotation): 注解是元数据,提供了在编译时和运行时对代码进行描述的...

Global site tag (gtag.js) - Google Analytics