内部类
定义
可以将一个类的定义放在另一个类的定义内部。
作用
一般来说,内部类继承自某个类或实现某个接口,内部类的代码操作创建它的外围类的对象。所以可以认为内部类提供了某种进入其外围类的窗口。
每个内部类都能独立地继承自一个(接口)的实现,所以无论外围类是否已经继承了某个(接口)的实现,对于内部类没有影响。
如何创建内部类
下面demo讲述了创建内部类和使用内部类。
package InnerClass;
public class InnerClassDemo {
class Inner {
public void f()
{
System.out.println("this is inner class.");
}
}
public Inner getInner()
{
return new Inner();
}
public static void main(String[] args) {
InnerClassDemo demo = new InnerClassDemo();
InnerClassDemo.Inner inner = demo.getInner();
inner.f();
}
}
如何链接到外部类
- 内部类自动拥有对其外围类所有成员的访问权
- 内部类的对象只能在其外围类的对象相关联的情况下才能被创建
package InnerClass;
public class InnerClassDemo {
private String str;
public InnerClassDemo(String s)
{
this.str = s;
}
class Inner {
public String getStr()
{
System.out.println(str);
return str;
}
}
public Inner getInner()
{
return new Inner();
}
public static void main(String[] args) {
InnerClassDemo demo = new InnerClassDemo("CodeAm");
InnerClassDemo.Inner inner = demo.getInner();
inner.getStr();
}
}
内部类和向上转型
向上转型:从一个子类(比较专用的类型向较通用类型转换)向基类转换的过程。
package InnerClass;
public interface Content {
String showContent();
}
package InnerClass;
public interface Destinaton {
String defineSomeThings();
}
package InnerClass;
public class InnerClassDemo {
public static void main(String[] args) {
InnerClass innerClass = new InnerClass();
innerClass.getContent().showContent();
innerClass.getDestination().defineSomeThings();
}
}
class InnerClass
{
private class pContent implements Content{
@Override
public String showContent() {
System.out.println("pContent");
return "pcontent";
}
}
protected class pDestination implements Destinaton
{
@Override
public String defineSomeThings() {
System.out.println("define pDestination");
return "define pDestination";
}
}
public Content getContent()
{
return new pContent();
}
public Destinaton getDestination()
{
return new pDestination();
}
}
在方法和作用域内的内部类
使用原因:
- 实现了某类型的接口,于是可以创建并且返回对其的引用
- 解决一个复杂问题,向创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的
匿名内部类
匿名内部类的主要作用:省去了新建类来实现接口方法,只是==return==一个向上转型类的引用,即
new Destinaton{...}
package InnerClass;
public class InnerClassDemo {
public Destinaton getStr(String s)
{
return new Destinaton(){
private String str=s;
@Override
public String defineSomeThings() {
System.out.println(str);
return str;
}
};
}
public static void main(String[] args) {
InnerClassDemo innerClassDemo = new InnerClassDemo();
Destinaton des = innerClassDemo.getStr("CodeAm");
des.defineSomeThings();
}
}
匿名内部类与工厂方法的美妙结合
package InnerClass;
interface Service {
void method1();
void method2();
}
interface ServiceFactory{
Service getService();
}
class ServiceImp1 implements Service
{
private ServiceImp1() {};
@Override
public void method1() {
System.out.println("this is ServicrImp1 method1");
}
@Override
public void method2() {
System.out.println("this is ServicrImp1 method2");
}
public static ServiceFactory factory = new ServiceFactory() {
@Override
public Service getService() {
return new ServiceImp1();
}
};
}
class ServiceImp2 implements Service {
private ServiceImp2() {};
@Override
public void method1() {
System.out.println("this is ServicrImp2 method1");
}
@Override
public void method2() {
System.out.println("this is ServicrImp2 method2");
}
public static ServiceFactory factory = new ServiceFactory() {
@Override
public Service getService() {
return new ServiceImp2();
}
};
}
public class Factoties {
public static void serviceConsumer(ServiceFactory factory)
{
Service s = factory.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(ServiceImp1.factory);
serviceConsumer(ServiceImp2.factory);
}
}
嵌套类
- 要创建嵌套类的对象,并不需要外围类
- 不能从嵌套类的对象中访问非静态的外围类对象
- 普通内部类不能有static数据和static字段,也不能包含嵌套类
import static java.lang.Math.*;
public class demo1 {
public static class StaticClassOne
{
private String str1 = "class one";
}
private static class StaticClassTwo
{
private String str2 = "calss two";
}
public static class StaticClassThree
{
private static class StaticClassFour
{
}
}
public static void main(String[] args) {
StaticClassTwo staticClassTwo = new StaticClassTwo();
System.out.println(staticClassTwo.str2);
}
}
继承内部类
// innerclasses/InheritInner.java
// Inheriting an inner class
class WithInner {
class Inner {}
}
public class InheritInner extends WithInner.Inner {
//- InheritInner() {} // Won't compile
InheritInner(WithInner wi) {
wi.super();
}
public static void main(String[] args) {
WithInner wi = new WithInner();
InheritInner ii = new InheritInner(wi);
}
}
可以看到,InheritInner 只继承自内部类,而不是外围类。但是当要生成一个构造器时,默认的构造器并不算好,而且不能只是传递一个指向外围类对象的引用。此外,必须在构造器内使用如下语法:
enclosingClassReference.super();
内部类标识符
由于编译后每个类都会产生一个.class 文件,其中包含了如何创建该类型的对象的全部信息(此信息产生一个"meta-class",叫做 Class 对象)。
java类命名规范:
- 外围类名字$内部类名字.class
- 如果内部类是匿名内部类那么编译器会产生一个简单的数字作为其标识符