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

java内部类

    博客分类:
  • Java
阅读更多
外创建内部类就是把类定义至于外围类的里面
public class Parcel1 {
	class Destination {
		private String label;

		Destination(String whereTo) {
			label = whereTo;
		}

		String readLabel() {
			return label;
		}
	}

	//在类的的函数中使用内部类,与使用普通类没多大区别
	public void ship(String dest) {
		Destination d = new Destination(dest);
		System.out.println(d.readLabel());
	}

	public static void main(String[] args) {
		Parcel1 p = new Parcel1();
		p.ship("Tasmania");
	}
}

如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,必须具体地知名这个对象饿类型(OuterClassName.InnerClassName),比如
public class Parcel2 {
	class Contents {
		private int i = 11;

		public int value() {
			return i;
		}
	}

	public Contents contents() {
		return new Contents();
	}

	public void ship(String dest) {
		Contents c = contents();
		Destination d = to(dest);
		System.out.println(d.readLabel());
	}

	public static void main(String[] args) {
		Parcel2 p = new Parcel2();
		p.ship("Tasmania");
		Parcel2 q = new Parcel2();
		// Defining references to inner classes:
		Parcel2.Contents c = q.contents();
	}
}

外部类拥有其外围类的所有元素的访问权
如果你需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this,如下:
public class DotThis {
	void f() {
		System.out.println("DotThis.f()");
	}

	public class Inner {
		public DotThis outer() {
			//通过外部类名字后面紧跟远点和this获取外部类对象			//的引用
			return DotThis.this;
		}
	}

	public Inner inner() {
		return new Inner();
	}

	public static void main(String[] args) {
		DotThis dt = new DotThis();
		DotThis.Inner dti = dt.inner();
		//通过获取到的外部类调用外部类中的方法
		dti.outer().f();
	}
}

如果你要在main函数中创建一个内部类对象,你必须在new表达式中提供对其他外部类对象的引用,这是需要使用.new语法,比如上例代码在main中修改创建内部类Inner对象的方法改为DotThis.Inner dti = dt.new Inner()后效果一样
在拥有外部类对象之前是不可能创建内部类对象,因为内部类对象会暗暗地连接到创建它的外部类对象上,但是如果你创建的是嵌套类(静态内部类),就不需要对外部类对象的引用

在方法的作用域内(而不是在其他类的作用域内)创建一个完整的类.这被称作局部内部类:
public interface Destination {
  String readLabel();
}

public class Parcel5 {
	public Destination destination(String s) {
		class PDestination implements Destination {
			private String label;

			private PDestination(String whereTo) {
				label = whereTo;
			}

			public String readLabel() {
				return label;
			}
		}
		return new PDestination(s);
	}

	public static void main(String[] args) {
		Parcel5 p = new Parcel5();
		Destination d = p.destination("Tasmania");
	}
}

PDestination类是destination()方法的一部分,所以在destination()之外不能访问,在return语句中的向上转型,返回的是Destination的引用,是一个基类
你也可以再同一个子目录下的任意类中对某个内部类使用类标示符PDestination,因为定义在方法内部,所以不会出现命名冲突.

在任意的作用域内嵌入一个内部类,比如在if语句的作用域内:
public class Parcel6 {
	private void internalTracking(boolean b) {
		if (b) {
			class TrackingSlip {
				private String id;
				TrackingSlip(String s) {
					id = s;
				}
				String getSlip() {
					return id;
				}
			}
			TrackingSlip ts = new TrackingSlip("slip");
			String s = ts.getSlip();
		}
	}
	public void track() {
		internalTracking(true);
	}
	public static void main(String[] args) {
		Parcel6 p = new Parcel6();
		p.track();
	}
}

这并不是说该类的创建时有条件的,它其实与别的类一起编译过了,然而,在定义TrackingSlip的作用域之外,它是不可用的,除此之外,与普通的类一样

匿名内部类,一直看起来有点奇怪
public interface Contents {
  int value();
}
public class Parcel7 {
	public Contents contents() {
		return new Contents() {
			private int i = 11;
			public int value() {
				return i;
			}
		}; 	
	}
	public static void main(String[] args) {
		Parcel7 p = new Parcel7();
		Contents c = p.contents();
		System.out.println(c.value());
	}
}

将返回值的生成与表示这个返回值的类的定义结合在一起,另外这个类是匿名的, 它没有名字.其实匿名类是非匿名类,然后去实现一个接口的简化形式

如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用时final的
public interface Destination {
  String readLabel();
}

public class Parcel9 {
	//参数dest必须定义成final的,才能在匿名内部类中使用
	public Destination destination(final String dest) {
		return new Destination() {
			private String label = dest;
			public String readLabel() {
				return label;
			}
		};
	}
	public static void main(String[] args) {
		Parcel9 p = new Parcel9();
		Destination d = p.destination("Tasmania");
		System.out.println(d.readLabel());
	}
}


匿名内部类不可能有命名构造器(因为它根本没名字),但通过实例初始化,能够达到为匿名内部类创建一个构造器的效果
abstract class Base {
	public Base(int i) {
		System.out.print("Base constructor, i = " + i);
	}
	public abstract void f();
}
public class AnonymousConstructor {
	//这里i不用声明为final,因为不会再匿名内部类被直接使用
	public static Base getBase(int i) {
		return new Base(i) {
			{
				System.out.print("Inside instance initializer");
			}
			public void f() {
				System.out.print("In anonymous f()");
			}
		};
	}
	public static void main(String[] args) {
		Base base = getBase(47);
		base.f();
	}
}


下面来看一段代码
public class Parcel10 {
	public Destination destination(final String dest, final float price) {
		return new Destination() {
			private int cost;
			// 这里的if语句不能作为字段初始化的一部分来执行
			{
				cost = Math.round(price);
				if (cost > 100)
					System.out.println("Over budget!");
			}
			private String label = dest;

			public String readLabel() {
				return label;
			}
		};
	}

	public static void main(String[] args) {
		Parcel10 p = new Parcel10();
		Destination d = p.destination("Tasmania", 101.395F);
	}
}

对于匿名类而言,实例初始化的实际效果就是构造器,当然它受到了限制-----不能重载实例化方法,所以你仅有一个这样的构造器
匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备.而且如果是实现接口,也只能实现一个接口

利用匿名内部类,定义工厂方法
interface Service {
	void method1();

	void method2();
}

interface ServiceFactory {
	Service getService();
}

class Implementation1 implements Service {
	private Implementation1() {
	}

	public void method1() {
		System.out.println("Implementation1 method1");
	}

	public void method2() {
		System.out.println("Implementation1 method2");
	}

	public static ServiceFactory factory = new ServiceFactory() {
		public Service getService() {
			return new Implementation1();
		}
	};
}

class Implementation2 implements Service {
	private Implementation2() {
	}

	public void method1() {
		System.out.println("Implementation2 method1");
	}

	public void method2() {
		System.out.println("Implementation2 method2");
	}
	//利用匿名内部类的方式实现一个接口,实现工厂的方式得到当前类
	public static ServiceFactory factory = new ServiceFactory() {
		public Service getService() {
			return new Implementation2();
		}
	};
}

public class Factories {
	public static void serviceConsumer(ServiceFactory fact) {
		Service s = fact.getService();
		s.method1();
		s.method2();
	}

	public static void main(String[] args) {
		serviceConsumer(Implementation1.factory);
		serviceConsumer(Implementation2.factory);
	}
}


建议:优先实用类而不是接口,如果你的设计中需要某个接口,你必须了解它,否则.不到迫不得已,不要将其放到你的设计中

如果不需要内部类对象与其外围类对象之间有联系,那么可以讲内部类声明为static.通常称为嵌套类,当内部类是static时,意味着:

    [1]要创建嵌套类的对象,并不需要其外围类的对象
    [2]不能从嵌套类的对象中访问非静态的外围类对象

嵌套类与普通的内部类还有一个区别:普通内部类的字段的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类.但是在嵌套类里可以包含所有这些东西
public class Parcel11 {
	private static class ParcelContents implements Contents {
		private int i = 11;
		public int value() {
			return i;
		}
	}
	protected static class ParcelDestination implements Destination {
		private String label;
		private ParcelDestination(String whereTo) {
			label = whereTo;
		}
		public String readLabel() {
			return label;
		}
		// 嵌套类可以包括其他静态元素
		public static void f() {
		}
		static int x = 10;
		static class AnotherLevel {
			public static void f() {
			}
			static int x = 10;
		}
	}
	public static Destination destination(String s) {
		return new ParcelDestination(s);
	}
	public static Contents contents() {
		return new ParcelContents();
	}
	public static void main(String[] args) {
		Contents c = contents();
		Destination d = destination("Tasmania");
	}
}


正常情况下,不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,你放到接口中的任何类都自动的是public和static.因为类是static,只是将嵌套类至于接口的命名空间内.你甚至可以再内部类中实现其外围接口
public interface ClassInInterface {
	void howdy();

	class Test implements ClassInInterface {
		public void howdy() {
			System.out.println("Howdy!");
		}

		public static void main(String[] args) {
			new Test().howdy();
		}
	}
}


以前一直不知道,嵌套类竟然可以这样用
public class TestBed {
  public void f() { System.out.println("f()"); }
  public static class Tester {
    public static void main(String[] args) {
      TestBed t = new TestBed();
      t.f();
    }
  }
}

就是可以把main方法放在嵌套类中

一个内部类被嵌套多少层不重要,它能透明地访问所有它所嵌入的外围类的所有成员,如下
class MNA {
	private void f() {
	}
	class A {
		private void g() {
		}
		public class B {
			void h() {
				//访问A对象的g方法
				g();
				//访问MNA对象的f方法
				f();
			}
		}
	}
}

public class MultiNestingAccess {
	public static void main(String[] args) {
		MNA mna = new MNA();
		MNA.A mnaa = mna.new A();
		MNA.A.B mnaab = mnaa.new B();
		mnaab.h();
	}
}
分享到:
评论
15 楼 dakai 2010-04-14  
基本用不上内部类
14 楼 guoliang1114 2009-12-23  
在看某个end-to-end 的时候,多次用到了内部类。还不能领会精髓啊
13 楼 DoubleEO 2009-12-23  
这不都是Thinking in java的吗,一摸一样,LZ从电子书复制的?
12 楼 咖啡猪猪 2009-12-01  
全都是《Thinking in java》上的例子,还以为有点特别的理解,失望....
11 楼 wxq276 2009-10-24  
用的很少,在和某种设计模式一起使用时匿名内部类用地比较多吧
10 楼 myworkfirst 2009-10-24  
   使用场景比较少
9 楼 lemonweirui 2009-10-23  
静态内部类和匿名内部类用的稍多。
8 楼 dragonzhong 2009-10-23  
这个think in Java 里面写的很详细,这本书很强大
7 楼 caiwenhn2008 2009-10-23  
内部类不好重用  使用本身还这么复杂   唯一用过的是在测试类中做一些mock类
6 楼 banrui 2009-10-23  
基本上没怎么用到内部类
5 楼 qiren83 2009-10-23  
写得很好,平时我不怎么用到类部类 同意husai对于内部类的看法
学习了
4 楼 akunamotata 2009-10-23  
对内部类说的很详细...不过内部类从维护的层面上来说,个人建议能少用就少用...
3 楼 qqj_1979 2009-10-23  
内部类使用起来还是比较难以驾驭!
2 楼 husai 2009-10-23  
看到最后,有些失望,内隐类的很大的用处是使java从功能上实现多重继承。没看到这个说明...
lz的例子《thinking in Java》中都讲过的....
1 楼 luckaway 2009-10-23  
内部类是个好东西,关键是如何运用它!!!

相关推荐

    java内部类详解

    Java 内部类详解 Java 内部类是一种高级特性,允许在一个类的定义内部创建另一个类。这种设计模式提供了更灵活的代码组织方式,同时还可以实现特定的封装和访问控制。内部类主要分为四种类型:静态内部类、成员内部...

    Java内部类总结

    ### Java内部类总结 在Java编程语言中,内部类是一个重要的概念,它允许开发者在一个类的内部定义另一个类。这种特性极大地增强了代码的封装性和复用性,同时也为解决特定问题提供了灵活的方法。本文将围绕Java内部...

    java内部类的讲解

    ### Java内部类详解 #### 一、内部类的分类与概念 Java的内部类机制是其强大特性之一,它允许类作为另一个类的成员存在,从而增强了代码的封装性和复用性。根据定义和作用域的不同,Java内部类主要分为四类: 1. ...

    Java 内部类

    Java 内部类是Java语言特性中的一个重要组成部分,它允许我们在一个类的内部定义另一个类。内部类可以访问外部类的所有成员,包括私有成员,这使得内部类在实现复杂逻辑和封装上具有很大的灵活性。下面我们将详细...

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

    ### Java内部类的应用场景 #### 场景一:当某个类除了它的外部类,不再被其他的类使用时 内部类的使用场景之一是当某个类仅需被其外部类使用时。这种情况下,将此类定义为内部类可以提高代码的封装性和可维护性。 ...

    java内部类使用例子

    Java内部类是Java语言提供的一种独特特性,它允许我们在一个类的定义内部定义另一个类。这种内部类可以是成员内部类、局部内部类、匿名内部类或静态内部类,每种都有其特定的用途和使用场景。在这个"java内部类使用...

    12.java内部类.zip

    12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类...

    java 内部类应用

    Java内部类是Java语言的一个特色特性,它允许我们在一个类的内部定义另一个类。这种设计模式在处理一些特定情况时非常有用,例如实现匿名回调、封装特定逻辑或创建与外部类有紧密关系的类。本篇文章将深入探讨Java...

    JAVA 内部类 PPT

    Java内部类是Java语言的一个独特特性,它允许我们在一个类的内部定义另一个类。这种设计提供了更高级别的封装和组织代码的方式。以下是关于内部类及其相关知识点的详细说明: 1. **内部类基本语法** - **实例内部...

    JAVA内部类总结

    ### JAVA内部类总结 在Java编程语言中,内部类(Inner Classes)是一种非常重要的特性,它允许我们在一个类的内部定义另一个类。这种结构不仅能够提高代码的组织性,还能帮助我们更好地处理类与类之间的关系。根据...

    java 内部类使用(内部匿名类)

    Java内部类是Java语言提供的一种独特机制,它允许在一个类的内部定义另一个类。这种设计模式使得代码结构更紧凑,可以更好地封装和隐藏实现细节,同时也增强了代码的复用性。内部类分为几种类型,包括成员内部类、...

    java内部类总结(含概念和实例)

    Java 内部类总结 Java 内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用 protected 和 private 修饰(而外部类只能使用 public 和缺省的包...

    java 内部类 局部内部类 匿名类 实例代码

    Java内部类是Java语言特性中一个独特而强大的部分,它允许在一个类的内部定义另一个类。内部类可以访问外部类的所有成员,包括私有成员,这使得内部类在实现某些特定设计模式时非常有用。本篇文章将深入探讨Java中的...

    Java语法总结 - 内部类

    Java内部类详解 Java内部类是Java语言中的一种特殊类别,它是指定义在另外一个类内部的类。内部类可以访问外部类的所有成员变量和方法,包括私有的变量和方法。内部类可以分为四种:成员内部类、静态嵌套类、方法...

    Java内部类的四个应用场景

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

    java内部类使用总结

    Java内部类是Java语言中一个独特且强大的特性,它允许我们在一个类的内部定义另一个类。内部类提供了增强封装的能力,使得内部类可以被隐藏在外部类中,仅对外部类可见,从而增加了代码的隐私性和安全性。同时,内部...

    Java内部类的作用

    ### Java内部类的作用 #### 一、定义及概念 内部类,顾名思义,指的是一个定义在另一个类内部的类。这样的结构让内部类能够访问外部类的成员(包括私有成员),并且允许内部类拥有不同的访问级别,如`private`、`...

    Java内部类_动力节点Java学院整理

    Java内部类是Java语言的一个重要特性,它允许我们在一个类的内部定义另一个类。这种设计模式使得代码结构更加紧凑,同时也提供了更高级的封装和抽象。内部类主要有两种类型:成员内部类和局部内部类。 1. 成员内部...

Global site tag (gtag.js) - Google Analytics