java in a nutshell_【笔记】java in a Nutshell <2>

类定义中,有4种常见的成员

类字段、类方法

实例字段、实例方法

5种常见的引用类型: class, interface, array, enumerated, annotation

public class Integer extends Number implements Serializable, Comparable {

// class members go here

}

abstract class 抽象类,

无法被实例化

任何包含一个抽象方法的类都必须是抽象类

final class

该类无法被继承(扩展)

一个类无法同时声明为abstract 和 final

volatile表示类中字段,可能被多个线程同时调用,读取必须从主存到主存,不能从cpu缓存中读取

一般,类中static field都和final一起使用,用于定义常量

类字段:

可以当作全局变量

没有必要赋予初始化值,编译器将会给定初始值(如果没有初始值)

类方法:

可以看成是全局方法

可以使用同一个类中任意的类字段和类方法, 或者其他类中的类方法和类字段

无法使用类中的实例字段和实例方法

实例字段:

是面向对象编程的关键,保存着对象的状态信息,用于区别不同的对象

没有必要赋予初始化值,编译器将会给定初始值(如果没有初始值)

实例方法:

可以使用所有同一个对象实例的字段

可以使用类字段、类方法

对象可以看作是一组状态(通过实例字段)和在此状态下的一组行为(通过实例方法)的集合

this:

通常情况下,不需要显示声明this(当引用对象实例中的成员)

当本地变量或者实例方法中的变量名称和类字段相同时候,需要使用this

类构造函数:

任意类都至少有一个构造函数,用于创建对象后,进行对象初始化

如果源码中没有定义构造函数,javac编译器将创建一个默认的构造函数(没有传参,也没有特殊初始化)

有关名称、声明、编写构造函数:

名称总是和类名称相同;

声明中没有返回值类型

内部为初始化对象实例代码,相当于构造this引用的属性

没有返回值

定义多个构造函数类似于重载方法

构造函数中可以使用this, 调用该类中的其他构造函数

类字段初始化 vs 实例字段初始化

类字段初始化

javac编译器自动生成一个类初始化方法

类字段将在该初始化方法中真正初始化

通常在类首次调用之前(类第一次加载到jvm中),调用类初始化方法

也可以自定义一些类初始化块,它们将会合并到类初始化方法中(自动生成)

// We can draw the outline of a circle using trigonometric functions

// Trigonometry is slow, though, so we precompute a bunch of values

public class TrigCircle {

// Here are our static lookup tables and their own initializers

private static final int NUMPTS = 500;

private static double sines[] = new double[NUMPTS];

private static double cosines[] = new double[NUMPTS];

// Here's a static initializer that fills in the arrays

static {

double x = 0.0;

double delta_x = (Circle.PI/2)/(NUMPTS-1);

for(int i = 0, x = 0.0; i < NUMPTS; i++, x += delta_x) {

sines[i] = Math.sin(x);

cosines[i] = Math.cos(x);

}

}

// The rest of the class is omitted...

}

实例字段初始化

java编译器将自动生成字段的初始化代码,并且将之加入构造函数中

按照实例字段出现的顺序先后,将实例字段添加到构造函数中

如果构造函数1通过this调用构造函数2, 构造函数2中才会实际处理初始化字段

public class SampleClass {

public int len = 10;

public int[] table = new int[len];

public SampleClass() {

for(int i = 0; i < len; i++) table[i] = i;

}

// The rest of the class is omitted...

}

public SampleClass() {

len = 10;

table = new int[len];

for(int i = 0; i < len; i++) table[i] = i;

}

子类和继承:

通过关键字extends实现继承

public class PlaneCircle extends Circle {

// We automatically inherit the fields and methods of Circle,

// so we only have to put the new stuff here.

// New instance fields that store the center point of the circle

private final double cx, cy;

// A new constructor to initialize the new fields

// It uses a special syntax to invoke the Circle() constructor

public PlaneCircle(double r, double x, double y) {

super(r); // Invoke the constructor of the superclass, Circle()

this.cx = x; // Initialize the instance field cx

this.cy = y; // Initialize the instance field cy

}

public double getCentreX() {

return cx;

}

public double getCentreY() {

return cy;

}

// The area() and circumference() methods are inherited from Circle

// A new instance method that checks whether a point is inside the circle

// Note that it uses the inherited instance field r

public boolean isInside(double x, double y) {

double dx = x - cx, dy = y - cy; // Distance from center

double distance = Math.sqrt(dx*dx + dy*dy); // Pythagorean theorem

return (distance < r); // Returns true or false

}

}

final 类:

类描述符final表示该类无法被继承, 例如:java.lang.String

父类,object类,类结构:

一个类只能有一个直接父类

每一个自定义的类都有一个父类,如果类没有被extends显示声明,其父类为java.lang.Object

object类是java中唯一没有父类的类

其他所有类都继承自object类(直接或者间接)

fb942cca7e0c8c951677945897432578.png

子类构造函数:

想要调用父类的构造函数,调用super()函数

只能在构造函数中调用super()

子类构造函数中,需要先调用super(), 然后再声明本地变量

构造函数链和默认构造函数:

每次创建新的对象实例时候,都会调用构造函数;

每次子类创建新的对象实例时候,都会调用父类的构造函数;

如果子类的构造函数没有this()或者super()调用父类的构造函数,javac编译器将会隐性添加super()没有参数的父类构造函数

若子类调用的父类构造函数没有显示声明,则会产生编译错误

类无法被实例化,如果类中定义了私有构造函数

隐藏父类字段

如果子类中有父类同名的字段,父类的同名字段被隐藏;所以,尽量不使用同名的字段;

隐藏父类字段不仅是实例字段,还有类字段

隐藏父类方法

当子类定义了一个实例方法,该方法和父类的实例方法有相同的名称、返回类型、传参列表,则父类中的实例方法将会被隐藏

实例方法隐藏

public class Car {

public static final double LITRE_PER_100KM = 8.9;

protected double topSpeed;

protected double fuelTankCapacity;

private int doors;

public Car(double topSpeed, double fuelTankCapacity, int doors) {

this.topSpeed = topSpeed;

this.fuelTankCapacity = fuelTankCapacity;

this.doors = doors;

}

public double getTopSpeed() {

return topSpeed;

}

public int getDoors() {

return doors;

}

public double getFuelTankCapacity() {

return fuelTankCapacity;

}

public double range() {

return 100 * fuelTankCapacity / LITRE_PER_100KM;

}

}

public class SportsCar extends Car {

private double efficiency;

public SportsCar(double topSpeed) {

super(topSpeed, 50.0, 2);

if (topSpeed > 200.0) {

efficiency = 200.0 / topSpeed;

} else {

efficiency = 1.0;

}

}

public double getEfficiency() {

return efficiency;

}

@Override

public double range() {

return 100 * fuelTankCapacity * efficiency / LITRE_PER_100KM;

}

}

3.上面的是对象实例方法的负载,类方法有不同的表现,类方法无法被覆盖,但是可以被隐藏

重写不是隐藏:

class A { // Define a class named A

int i = 1; // An instance field

int f() { return i; } // An instance method

static char g() { return 'A'; } // A class method

}

class B extends A { // Define a subclass of A

int i = 2; // Hides field i in class A

int f() { return -i; } // Overrides method f in class A

static char g() { return 'B'; } // Hides class method g() in class A

}

public class OverrideTest {

public static void main(String args[]) {

B b = new B(); // Creates a new object of type B

System.out.println(b.i); // Refers to B.i; prints 2

System.out.println(b.f()); // Refers to B.f(); prints -2

System.out.println(b.g()); // Refers to B.g(); prints B

System.out.println(B.g()); // A better way to invoke B.g()

A a = (A) b; // Casts b to an instance of class A

System.out.println(a.i); // Now refers to A.i; prints 1

System.out.println(a.f()); // Still refers to B.f(); prints -2

System.out.println(a.g()); // Refers to A.g(); prints A

System.out.println(A.g()); // A better way to invoke A.g()

}

}

查找虚拟方法:

假设,Car[]中包含了Car类和其子类SportsCar对象实例,javac编译器在编译时候,无法知道调用的实例方法range()该使用Car类的实例方法还是SportsCar的实例方法;

javac编译器创建字节码,使用虚拟函数寻找在运行时候,当解释器运行字节码时候,解释器将获取适当的range()实例方法,相对于每一个Car[]中的实例对象

C++等语言中,没有虚拟函数寻找机制,它们的替代方案是使用virtual关键字,如果子类被允许重写实例方法,则需要显示声明virtual

调用一个重写方法

class A {

int i = 1; // An instance field hidden by subclass B

int f() { return i; } // An instance method overridden by subclass B

}

class B extends A {

int i; // This field hides i in A

int f() { // This method overrides f() in A

i = super.i + 1; // It can retrieve A.i like this

return super.f() + i; // It can invoke A.f() like this

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值