Java逍遥游记_Java逍遥游记读书笔记<二>

Static

由于静态方法不需要通过实现实例就可以被调用,所以在静态方法中不能使用this关键字(它不知道this指的是谁,因为没有实例);也不能直接访问实例变量和实例方法(没有实例哪来的实例变量和实例方法);但是可以直接访问静态变量和静态方法。

静态方法必须被实现,为什么

因为静态方法不依赖类的实例而存在,所以当前类必须为静态方法提供实现,换句话说,一个静态的方法不能定义为抽象的方法。即static和abstract不能同时使用。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classTest

{int x;//x是一个实例变量,不能被静态方法直接访问

Test()

{

x= 1;

}public static voidmain(String[] args)

{

System.out.println(x);

}

}

错误的Test.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classTest

{intx;

Test()

{

x= 1;

}public static voidmain(String[] args)

{

Test t1= newTest();

System.out.println(t1.x);

}

}

正确的Test.java

接口

Seller.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

interface Cal_Int //接口

{double mul(double a, double b); //public abstract

}class Cal implements Cal_Int //实现接口的类

{public double mul(double a, double b) //must public

{return a*b;

}

}classSeller

{

Cal_Int cal;publicSeller(Cal_Int cal)

{this.cal =cal;

}public void compute(double price, doubleamount)

{

System.out.println(cal.mul(price, amount));

}public static voidmain(String[] args)

{

Cal_Int cal= new Cal(); //定义接口类型的引用变量,引用了实现该接口的类的实例

Seller seller= newSeller(cal);

seller.compute(0.1, 16);

}

}

View Code

通俗来讲,接口就是一个类似抽象类的东西。

如果一个类需要用到接口,那么该类只需按照接口给出的函数调用即可,而不关心它是怎么实现的(就像调用API一样)

如果一个类需要实现接口,那么该类就要覆盖(override)接口给出的函数。(Android中的implements OnClickListener,然后重写onClick函数)

接口中的成员变量默认且必须是public, static, final,必须被显示初始化。

接口中的方法默认且必须是public abstract。

接口没有构造方法。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public interfaceA

{public static final CONST2 = 2;int CONST = 1; //ok 默认是public static final

int var; //error static未显示初始化 接口中也没有构造方法可以初始化

void f(); //ok 默认是public, abstract

void f2(){}; //error 必须是abstract

protected void f3();//error 必须是public

public A(){} //error 接口中没有构造方法,因为没有实例

}

View Code

一个接口不能实现另一个接口,但是可以继承多个接口。

一个类只能继承一个父亲,但可以实现多个接口。

接口必须通过类来实现它的抽象方法。

当类实现接口的时候,必须实现接口中的所有方法,否则它将被定义为抽象类(不然就含有Abstract方法,那就必须是抽象类)。

不能直接创建接口的实例,但是可以定义接口类型的引用变量,该变量引用实现了该接口的类的实例(好好理解下这句话,不懂的话见上面Seller.java)。

this与super

Monkey.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classMonkey

{privateString name;private intage;public Monkey(String name, intage)

{this.name =name;this.age =age;

}public Monkey(String name) //缺省age的时候

{this(name, -1); //ok//Monkey(name, -1);//error 不能通过类名来调用

}public Monkey(int age) //缺省name的时候

{this("Anonymous", age);

}publicMonkey()

{this("Anonymous", -1); //缺省name和age的时候

}

}

View Code

同一个类中,在一个构造方法中,可以通过使用this来调用另一个重载的构造方法。而不能使用类名来调用,这点很重要。

this语句必须放在构造方法中的第一句。

Sub.java

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

classBase

{

Base(inti)

{

System.out.println(i);

}

}public class Sub extendsBase

{

Sub(inti)

{super(i);

}

Sub()

{super(0);

}public static voidmain(String[] args)

{

Sub sub= newSub();

Sub sub2= new Sub(1);

}

}

View Code

子类调用父类的构造方法一共有2种方式,一种是用super,另一种不使用super,系统自动调用父类的默认构造方法。

子类的构造方法中不能使用父类名字来调用父类的构造方法,而要使用super语句。

super语句必须放在子类构造方法中的第一句。

内部类

内部类:在一个类的内部定义的类就称为内部类。

内部类可以有4种访问级别:public,protected,默认和private。

顶层类(最外层的类)只能有2种访问级别:public和默认。(你什么时候见过最外层的类有protected和private修饰)

类内:

变量可以分为局部变量和成员变量,成员变量可以分为静态变量和实例变量。

内部类可以分为局部内部类和成员内部类,成员内部类可以分为静态内部类和实例内部类。

局部内部类:

局部内部类不能用public、protected、private和static修饰。

局部内部类可以直接访问外部类的所有成员以及所在方法中的final参数和变量。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

classA

{inta;public void f(final int p1, intp2)

{final int v1 = 2;int v2 = 1;classB

{int b1 = a; //ok

int b2 = p1; //ok

int b3 = p2; //error

int b4 = v1; //ok

int b5 = v2; //error

}

}

}

View Code

实例内部类:

1.

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{public classB

{

}private B b = new B(); //类内直接访问B

}

A.B b= new A().new B(); //类外访问要确保类名完整

View Code

这个例子中,内部类B的完整类名为A.B。若在类内,可以直接访问;若在类外,访问时类名要完整。

最后一句等价于

A a = newA();

A.B b= a.new B();

2.实例内部类可以直接访问外部类的所有成员变量和方法(任何级别的都可以)

为什么呢,因为当内部类B的实例存在的时候,它的外部类A的实例必定也存在,因此可以访问到。

可以设想一个儿子诞生的时候,必定有母亲的存在,所以他可以持有母亲有的东西。

3.外部类不能直接访问实例内部类的成员变量和方法,但可以访问实例内部类的实例的成员变量和方法。

这样理解,若一个母亲可能没有儿子,那这个时候怎么拿到儿子的东西呢?但是若是先创建了一个儿子,那么这个时候母亲就可以拿到了。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{public classB

{int x = 0;

}public voidf()

{int v1 = x; //error 万一内部类的实例没有创建呢

B b= newB();int v2 = b.x; //ok 通过实例去访问

}

}

View Code

静态内部类:

静态内部类用static修饰,不同于实例内部类,静态内部类的实例不依赖于外部类实例的存在。

1.创建静态内部类时,不需要创建外部类的实例。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{public static classB

{int x = 0;

}

}

A.B b= newA.B();

b.x= 2;

View Code

2.静态内部类可以直接访问外部类的静态成员,如果要访问实例成员,只能通过外部类的实例去访问。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{inta1;static inta2;public static classB

{int b1 = a1; //error

int b2 = a2; //ok

int b3 = new A().a1; //ok

}

}

View Code

3.可以通过完整的类名去访问静态内部类的静态成员。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{public static classB

{intv1;static intv2;

}

}

A.Bb= newA.B();

b.v1= 1; //ok

b.v2 = 2; //ok

A.B.v1 = 1; //error

A.B.v2 = 2; //ok

View Code

匿名类:

匿名类:没有名字的内部类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{

A()

{

System.out.println("Default Constructor");

}

A(intv)

{

System.out.println("Special Constructor");

}voidf()

{

System.out.println("from A");

}public static voidmain(String[] args)

{newA().f();

A a= new A() //定义了一个继承A的匿名类

{void f(){System.out.println("from anonymous");}//覆盖父类A的方法

};

a.f();

}

}

View Code

输出结果是

Default Constructor

from A

Default Constructor

from anonymous

这个语句

A a = new A() //定义了一个继承A的匿名类

{void f(){System.out.println("from anonymous");}//覆盖父类A的方法

};

定义了一个继承A的匿名类。相当于

class Sub extendsA

{void f(){System.out.println("from anonymous");}//覆盖父类A的方法

}

A a= new Sub();

所以这种情况可以看作是没有名字的子类。

1.匿名类本身没有构造方法,但会自动调用父类的构造方法。

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{

A()

{

System.out.println("Default Constructor");

}

A(intv)

{

System.out.println("Special Constructor");

}voidf()

{

System.out.println("from A");

}public static voidmain(String[] args)

{int v = 1;

A a= new A(v) //定义了一个继承A的匿名类

{void f(){System.out.println("from anonymous");}//覆盖父类A的方法

};

a.f();

}

}

View Code

Special Constructor

from anonymous

注意,如果在匿名类中使用了局部变量或参数,那该变量或参数必须是final。例如

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{

A()

{

System.out.println("Default Constructor");

}

A(intv)

{

System.out.println("Special Constructor");

}voidf()

{

System.out.println("from A");

}public static voidmain(String[] args)

{final int v = 1; //必须定义为final

A a = newA(v)

{void f(){System.out.println(v);}//使用了局部变量

};

a.f();

}

}

View Code

巧记:匿名类和局部内部类一样,访问到局部参数和变量的时候都必须是final类型的。

2.匿名类除了继承类,还可以实现接口

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classA

{public static voidmain(String[] args)

{

Thread t= new Thread //实现了Runnable接口

(newRunnable()

{public voidrun(){}

}

);

t.start();

}

}

View Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值