java 第10章_(Thinking in Java)第10章 内部类

Thinking in Java捞干货,写笔记

一、成员内部类

1.最基本使用

public class Demo {

class Contents{

private int i=11;

public int value(){

return i;

}

}

class Destination{

private String label;

Destination(String whereTo){

label=whereTo;

}

String readLabel(){

return label;

}

}

public void ship(String dest){

Contents c=new Contents();

Destination d=new Destination(dest);

System.out.println(d.readLabel());

}

public static void main(String[] args) {

Demo d=new Demo();

d.ship("Tasmania");

}

}

2.内部类可以访问外部类的成员

内部类可以访问外部类的成员变量。如下:

public class Demo {

private Object[] items;

private int next = 0;

public Demo(int size) {

items = new Object[size];

}

public void add(Object x) {

if (next < items.length) {

items[next++] = x;

}

}

private class SequenceSelector implements Selector {

private int i = 0;

public boolean end() {

return i == items.length;

}

public Object current() {

return items[i];

}

public void next() {

if (i < items.length) {

i++;

}

}

}

public Selector selector() {

return new SequenceSelector();

}

public static void main(String[] args) {

Demo d = new Demo(10);

for (int i = 0; i < 10; i++) {

d.add(Integer.toString(i));

}

Selector selector = d.selector();

while (!selector.end()) {

System.out.print(selector.current() + " ");

selector.next();

}

}

}

interface Selector {

boolean end();

Object current();

void next();

}

因为在创建内部类对象的时候,内部类对象会捕获一个指向外部类对象的引用。访问外部类成员的时候,就是用这个引用来获取外部类成员的。内部类中也可以取得这个外部类对象引用。举例如下:

public class DotThis{

void f(){

System.out.println("DotThis.f()");

}

class Inner{

public DotThis outer(){

return DotThis.this;

//A plain "this" would be Inner's 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();

}

}

当要在其他类中创建一个内部类对象的时候,可以使用.new语法。

public class DotNew{

public class Inner{

}

public static void main(String[] args){

Inner dni=new DotNew().new Inner();

}

}

当创造内部类对象的时候,如果这个内部类不是嵌套类(静态内部类),那么就必须要通过外部类对象,才能创建这个内部类对象,为什么呢,之前说过,因为这个内部类对象要获取外部类的引用啊。

并且在存在多个内部类的时候,多个内部类之间可以互相创建对象。例子就不举了。

小结:现在所说的都是成员内部类,其实内部类没那么复杂,既然叫做成员内部类了,他就只是类的成员罢了。他也可以带修饰符,他的修饰符和其他普通的成员变量的修饰符的意义也没有什么不同。

3.内部类权限修饰符

当内部类被private修饰的时候,该类只能被外部类内的方法使用,其他类不能获取该内部类的引用,因为是private的,所以其他类根本不知道存在一个这样的类。当然也可以作为一个成员变量使用,但是如果作为成员变量,则其他类并不能直接创建内部类的引用,需要用其他手段获取该引用,如下:

class Outer{

Inner in;

private class Inner implements a_interface{

void show(){

System.out.println("123");

}

}

}

interface a_interface{

void show();

}

class test{

//Inner in=new Outer().in;这是错误的,因为test并不知道Outer类有一个Inner内部类,因为是私有的

a_interface in=new Outer().in;//可以运用向上转型的方法获取private修饰的内部类。

}

小结:其实这也很好记,无论是public还是private,修饰到内部类上的时候,和他们修饰普通的成员变量(如string,int之类)的时候没什么不同,规则都一样,public就都能使用,private就类内可以用。所以规则就记住三条就好:1.先考虑外部类的权限,是否可以获取一个外部类对象。2.创建成员内部类对象的时候需要外部类对象。3.考虑内部类的权限,是否可以获取这样的一个内部类对象(或者说,在外部知不知道有这样一个内部类)。

二、方法和作用域内的内部类

当我们需要解决一个复杂的问题,想创建一个类来辅助解决问题,但是不希望这个类是公共可用的,甚至不希望在外部类之内的其他地方可以访问到这个辅助类。我们可以运用方法内的内部类

public class Outer {

public InterfaceDemo get_InterfaceDemo(String s) {

class InterfaceDemoTool implements InterfaceDemo {

private String label;

private InterfaceDemoTool(String label) {

this.label = label;

}

public String readLabel() {

return label;

}

}

return new InterfaceDemoTool(s);

}

public static void main(String[] args) {

Outer o = new Outer();

InterfaceDemo i = o.get_InterfaceDemo("123");

}

}

interface InterfaceDemo {

String readLabel();

}

当然在方法中还可以定义多个内部类,并且这些内部类之间的关系和普通一个Java文件中多个类之间的关系好像没什么不同。也可以相互继承和创建对象。另外在方法中的内部类不能加private等权限修饰符,只能加abstract和final修饰符。

另外也可以在某个作用域内创建内部类对象

if(a==b){

class inner{

}

new inner();

}

三、匿名内部类

下面这块代码中get_inner()的意思是,创建一个继承自InnerFather的匿名类对象,并且自动向上转型为InnerFather后返回。

public class Outer {

public InnerFather get_inner() {

return new InnerFather() {

void print(){

System.out.println("Inner_Override");

}

};

}

class InnerFather {

InnerFather() {

}

void print(){

System.out.println("InnerFather");

}

}

public static void main(String[] args) {

Outer o = new Outer();

InnerFather i = o.get_inner();

i.print();

}

}

当然这只是有无参构造函数,当父类只有一个含参构造函数的时候,我们可以这样向匿名内部类传入一个构造函数参数。

public class Outer {

public InnerFather get_inner(int i) {

return new InnerFather(i) {

void print(){

System.out.println("Inner_Override");

}

};

}

class InnerFather {

InnerFather(int i) {

}

void print(){

System.out.println("InnerFather");

}

}

public static void main(String[] args) {

Outer o = new Outer();

InnerFather i = o.get_inner(10);

i.print();

}

}

可以通过构造代码块来实现匿名内部类的自定义的构造函数

abstract class Base {

public Base(int i) {

System.out.println("Base constructor");

}

public abstract void f();

}

public class AnonymousConstructor {

public static Base getBase(int i){

return new Base(i){

{System.out.println("AnonymousConstructor constructor");}

public void f(){

}

};

}

public static void main(String[] args) {

Base base = getBase(47);

}

}

(书上说,如果传入了新的对象,就比如下面例子中的s_in,这个s_in就必须是final的,但是我实验了一下发现并不用啊,我也没太搞懂。)

abstract class Base {

public Base(int i) {

System.out.println("Base constructor");

}

public abstract void f();

}

public class AnonymousConstructor {

public static Base getBase(int i,String s_in){

return new Base(i){

{System.out.println("AnonymousConstructor constructor");}//构造代码块4.嵌套类

String s=s_in;

public void f(){

}

};

}

public static void main(String[] args) {

Base base = getBase(47,"hello");

}

}

四、嵌套类

嵌套类指的是被static修饰的内部类。这意味着:1.创建嵌套类对象不需要外部类对象。2.不能再嵌套类对象之中访问非静态的外围类对象。普通内部类的成员和方法只能放在类的外部层次上(这句话我没搞懂= =),所以普通内部类不能有static的成员和方法。但是嵌套类可以有。

public class Outer {

static class Inner{

static int i=5;

}

public static void main(String[] args) {

Inner i=new Outer.Inner();

}

}

可以从上面的例子看到,在创建这个嵌套类对象的时候,并没有像最开始那样,用一个外部类对象来创建这个内部类对象。其实这和静态方法差不多。

可以在接口内部定义内部类,而且他们即使没有static修饰,也会自动变成public 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();

}

}

}

书上有句话说的很好,在开发的时候建议在每个类中都写一个main方法测试,但是这又必须带着那些已经编译过的额外代码,所以我们可以用嵌套类放置测试代码。

public class Outer {

public void f(){

System.out.println("I need to be tested");

}

public static class Tester{

public static void main(String[] args) {

Outer o=new Outer();

o.f();

}

}

}

当然以上两段代码如果是在eclipse上运行的话,需要设置一下运行的main函数在哪,否则会报错

d3d5c54165abda537b0e1bda4d89561a.png

五、多层内部类嵌套

纸老虎,爱有几层有几层,反正只要是外部类的东西,不管哪层外部类,都能访问到。

public class Outer {

void f(){

System.out.println("hello");

}

class Inner1{

void g(){

System.out.println("java");

}

class Inner2{

void h(){

f();

g();

}

}

}

public static void main(String[] args) {

Outer.Inner1.Inner2 in2=new Outer().new Inner1().new Inner2();

in2.h();

}

}

下面是个好玩的

public class Outer {

void f(){

System.out.println("hello");

}

class Inner1{

void f(){

System.out.println("java");

}

class Inner2{

void h(){

f();

}

}

}

public static void main(String[] args) {

Outer.Inner1.Inner2 in2=new Outer().new Inner1().new Inner2();

in2.h();

}

}

最后打印结果是java。

大概就这么多吧,以后如果还有新东西再补。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值