学习Java语言
面向对象编程概念
核心概念:对象,消息,类和继承
这一节会介绍 对象,类,继承,接口和包
What Is an Object?
An object is a software bundle of related state and behavior.
对象是相关属性和行为的软件集合。
将不同的实物对象成不同的对象,有以下好处
- 模块化
- 信息隐藏
- 代码复用
- 扩展性和易调试
What Is a Class?
A class is a blueprint or prototype from which objects are created.
类是创建的对象的蓝图或原型。
What Is Inheritance?
Inheritance provides a powerful and natural mechanism for organizing and structuring your software.
继承提供了一种强大且自然的机制来组织/构建程序。
面向对象编程允许从其他类继承公共有用的属性和行为。
使用 extends
关键字
class MountainBike extends Bicycle {
// new fields and methods defining
// a mountain bike would go here
}
What Is an Interface?
An interface is a contract between a class and the outside world.
接口是类和外部世界的约定。当一个类实现接口,他承诺提供接口发布的行为。
定义接口:
interface Bicycle {
// wheel revolutions per minute
void changeCadence(int newValue);
void changeGear(int newValue);
void speedUp(int increment);
void applyBrakes(int decrement);
}
实现接口,使用关键字implements
class ACMEBicycle implements Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
// The compiler will now require that methods
// changeCadence, changeGear, speedUp, and applyBrakes
// all be implemented. Compilation will fail if those
// methods are missing from this class.
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
What Is a Package?
A package is a namespace for organizing classes and interfaces in a logical manner.
包是以合理的方式来组织类和接口的一个命名空间。
把程序放到包里可以使得大项目易于管理。
语言基础
Java语言的基础特征:变量,数组,数据类型,操作符和控制流
Variables
Java 对象把属性保存在域中:
int cadence = 0;
int speed = 0;
int gear = 1;
"field" and "variable" 这两个概念是一样的。
Java 语言中有下列几种变量:
- 实例变量(Non-Staic Fields)
- 类变量(Static Fields)
- 本地变量: 临时变量
- 参数变量
命名规则:
- 变量名是大小写敏感的case-sensitive,字母,数字,美元符号""和下划线"_",长度没有限制,开头不能是数字。正常开头都是字母,而不用''和'_'. 并且正常都不使用,只有自动生成的名字中有。
- 使用全词来命名,而不是选择缩写。
- 不能使用关键字来命名
- 驼峰命名法
- 常量命名为大写,
static final int NUM_GEARS = 6;
为了方便,其他地方一般不使用下划线来命名。
Operators
Operators | Precedence |
---|---|
postfix | expr++ expr-- |
unary | ++expr --expr +expr -expr ~ ! |
multiplicative | * / % |
additive | + - |
shift | << >> >>> |
relational | < > <= >= instanceof |
equality | == != |
bitwise AND | & |
bitwise exclusive OR | ^ |
bitwise inclusive OR | | |
logical AND | && |
logical OR | || |
ternary | ? : |
assignment | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
Expressions, Statements, and Blocks
- 表达式
表达式是由变量,操作符和方法调用评估得到一个值。
表达式返回值的数据类型取决于表达式中的元素:
int cadence = 0;
表达式 cadence = 0
返回的类型就是int.
表达式支持混合运算:
1 * 2 * 3 / 4
为了避免产生歧义和错误,建议用小括号
x + y / 100 //有歧义
(x + y) / 100
x + (y / 100)
- 语句
Java 语句大致跟自然语言的句子相同。
语句形成表达式完整的单元。
下列几种表达式可以组成语句,并且用分号';'结束:- 赋值表达式
- 自增/自减操作
- 方法调用
- 对象创建表达式
// assignment statement
aValue = 8933.234;
// increment statement
aValue++;
// method invocation statement
System.out.println("Hello World!");
// object creation statement
Bicycle myBike = new Bicycle();
还有另外两种语句
5. 声明语句
6. 控制流
//declaration statement
double aValue = 8933.234;
//the decision-making statements
if-then, if-then-else, switch,
//the looping statements
for, while, do-while
//the branching statements
break, continue, return
- 块
块是0条或多条语句的组合,用大括号圈起来。
class BlockDemo {
public static void main(String[] args) {
boolean condition = true;
if (condition) { // begin block 1
System.out.println("Condition is true.");
} // end block one
else { // begin block 2
System.out.println("Condition is false.");
} // end block 2
}
}
Control Flow Statements
- 选择语句
if-then, if-then-else, switch
- 循环语句
for, while, do-while
- 分支语句
break, continue, return
类和对象
创建对象,使用对象
类
剖析类,以及怎样声明属性,方法和构成器
public class Bicycle {
// the Bicycle class has
// three fields
public int cadence;
public int gear;
public int speed;
// the Bicycle class has
// one constructor
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// the Bicycle class has
// four methods
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
几种变量:
- Member variables in a class—these are called fields.
- Variables in a method or block of code—these are called local variables.
- Variables in method declarations—these are called parameters.
变量声明:
- 0个或多个修饰符,例如public或private
- 类型
- 变量名
public int cadence;
权限修饰符:
public > protect > default > private
定义方法:
Here is an example of a typical method declaration:
public double calculateAnswer(double wingSpan, int numberOfEngines,
double length, double grossTons) {
//do the calculation here
}
返回类型 方法名 括号( 参数 ) { 方法体 }
方法命名:驼峰命名法
run
runFast
getBackground
getFinalData
compareTo
setX
isEmpty
重载方法:
通过不同的参数(类型,个数)来区别:
public class DataArtist {
...
public void draw(String s) {
...
}
public void draw(int i) {
...
}
public void draw(double f) {
...
}
public void draw(int i, double f) {
...
}
}
构造器:
A class contains constructors that are invoked to create objects from the class blueprint.
类调用构造器来创建对象。
构造器的声明和方法声明类似,有两点不同:
- 使用类名作方法名
- 没有返回类型
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
调用构造器来创建对象,用new
操作符
Bicycle myBike = new Bicycle(30, 0, 8);
一个类可以有多个构造器,他们之间的参数不同。
代码没有显示声明构造器的话,会有一个默认的无参构造器。
传递参数:
可以向方法或构造器传递参数。
参数的数量没有限制
Java中的参数传递都是值传递,基本类型和引用类型有点区别:
public class PassPrimitiveByValue {
public static void main(String[] args) {
int x = 3;
// invoke passMethod() with
// x as argument
passMethod(x);
// print x to see if its
// value has changed
System.out.println("After invoking passMethod, x = " + x); //这里x没有被修改
}
// change parameter in passMethod()
public static void passMethod(int p) {
p = 10;
}
}
执行结果是:
After invoking passMethod, x = 3
基本变量传递参数时,方法内对参数的修改只在本地生效,不会影响外层的值。
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/02
*/
public class Circle {
int x;
int y;
public Circle(int xx, int yy) {
x = xx;
y = yy;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public String toString() {
return "Circle [x=" + x + ", y=" + y + "]";
}
public void moveCircle(Circle circle, int deltaX, int deltaY) {
// code to move origin of circle to x+deltaX, y+deltaY
// circle指向的对象呗修改,外层的对象也跟着被修改,变成(27,62)
circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
System.out.println(circle);
// code to assign a new reference to circle
// 这里重新将circle变量指向新的对象(0,0),外层的circle依然是指向原来的对象(27,62)
// 外层的circle指向的对象不会被修改,不会指向其他对象,但是对象的属性值可以被修改。
circle = new Circle(0, 0);
System.out.println(circle);
}
public static void main(String[] args) {
Circle myCircle = new Circle(4, 6);
System.out.println(myCircle);
moveCircle(myCircle, 23, 56);
System.out.println(myCircle); //这里myCircle对象以及被修改了
}
}/**Output
Circle [x=4, y=6]
Circle [x=27, y=62]
Circle [x=0, y=0]
Circle [x=27, y=62]
*///~
这里的值传递,指的是引用的值,外层的circle指向的对象不会被修改,不会指向其他对象,但是对象的属性值可以被修改。
对象
As you know, a class provides the blueprint for objects; you create an object from a class.
Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);
创建对象的语句有三个部分:
- 声明:类型+对象名
Point originOne
- 实例化:
new
关键字是用来创建对象的Java操作符 - 初始化:new调用构造器来初始化对象
Point(23, 94)
使用对象:
objectReference.fieldName
objectReference.methodName(argumentList)
objectReference.methodName();
垃圾收集器:
The Java runtime environment deletes objects when it determines that they are no longer being used. This process is called garbage collection.
当对象不再被使用时,Java 运行环境会删除它。这个过程叫做垃圾回收。
An object is eligible for garbage collection when there are no more references to that object.References that are held in a variable are usually dropped when the variable goes out of scope. Or, you can explicitly drop an object reference by setting the variable to the special value null.
当没有应用指向对象的时候,它就是满足垃圾回收要求的。当变量离开作用域时,它的引用就会被删除。或者可以通过将变量赋值为null来删除引用。
更多关于类
这一节是关于类依赖于使用对象引用和.
操作符:
返回值
方法返回的三种情况:
1. 所有语句正常执行结束
2. return 语句
3. 抛出异常this 关键字
this关键字指向当前对象
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public class Rectangle {
private int x, y;
private int width, height;
public Rectangle() {
this(0, 0, 1, 1);
}
public Rectangle(int width, int height) {
this(0, 0, width, height);
}
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
...
}
- 访问控制
public > protect > default > private
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
no modifier | Y | Y | N | N |
private | Y | N | N | N |
- static 类变量和类方法
- 类变量
When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables.
当创建类的多个对象时,每个对象实例都有各自的实例变量。如果在变量前面加上static
关键字,这个变量就是类变量,是跟类关联在一起,而不是对象实例。
public class Bicycle {
private int cadence;
private int gear;
private int speed;
// add an instance variable for the object ID
private int id;
// add a class variable for the
// number of Bicycle objects instantiated
private static int numberOfBicycles = 0;
...
}
上面的numberOfBicycles
就是类变量 class variables or static fields.
2. 类方法
Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in
ClassName.methodName(args)
类方法可以直接用类名来调用,不需要先创建对象实例。也可以跟普通方法调用一样,使用 instanceName.methodName(args)
. 不过不推荐,因为这样就不能将类方法和普通方法区分开了。
类方法的常见用法就是用来访问类变量(静态域).
访问注意:
- 实例方法可以直接访问实例变量和实例方法;
- 实例方法可以直接访问类变量和类方法;
- 类方法可以直接访问类变量和类方法;
- 类方法不可以访问实例变量和实例方法-它们必须用一个对象引用才能访问;
- 类方法不能用this关键字,因为他不指向任何实例对象。
- 常量
static
和final
关键字的组合可以用来定义常量。
final 标识符表明这个域的值不能被修改。
static final double PI = 3.141592653589793;
如果想要改变PI的值,编译报错。
Note: If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.
如果一个基本类型或字符串类型被定义为常量,且编译阶段就知道常量的值,编译器就会在用到这个常量的所有地方把它替换为具体的值。这个叫做编译时常量。所以如果上面PI的值变成了3.975,那么就要重新编译来获取最新的值。
- 初始化域
public class BedAndBreakfast {
// initialize to 10
public static int capacity = 10;
// initialize to false
private boolean full = false;
}
Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.
没有要求一定要在类定义的开头声明域,尽管这是最常见的用法。只需要满足在使用域之前被初始化就可以。
Static Initialization Blocks 静态初始化块
static {
// whatever code is needed for initialization goes here
}
- 总结:创建,使用类和对象
A class declaration names the class and encloses the class body between braces.
类定义:命名类,并且用括号来圈起来类主体。
类主体包含域,方法和构造器。
- 域: 属性xinxi
- 方法:实现行为
- 构造器:初始化对象
类变量和类方法: static 关键字
实例变量和实例方法: 没有用static关键字
嵌套类
Java允许在一个类里面再定义一个类,这个类就叫做嵌套类。
class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
嵌套类是外部类的一个成员。
嵌套类分为两个两类:
- static 嵌套类不可以访问外部类的其他成员。
- non-static 嵌套类(inner classes) 可以访问外部类的其他成员
为什么使用嵌套类:
- It is a way of logically grouping classes that are only used in one place:如果一个类仅仅被其他一个类访问,那么可以将他们合理地嵌套在一起。
- It increases encapsulation: 提高封装特性。可以将内部类隐藏在外部类下
- It can lead to more readable and maintainable code:提高代码的易读性和可维护性。
静态内部类:
Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
静态内部类和它的外部类(或其他类)的实例成员的交互就像任何其他的顶层的类一样。
//可以使用外部类的名字来访问静态内部类
OuterClass.StaticNestedClass
//例如,可以使用下面的语法来创建静态内部类的对象
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
普通内部类
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.
类似实例方法和实例变量,内部类和外部类的一个实例对象相关联,可以直接访问这个实例对象的方法和域。而且,内部类是和实例对象相关联,所以里面不能定义任何静态成员。
一个内部类的实例只能存在域外部类的实例内。
要实例化内部类,必须先实例化外部类,然后用下面的语法来创建内部类:
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
普通内部类 Inner classes 分为两种:
- Local 本地内部类
- Anonymous 匿名内部类
内部类同样可以使用private,public和protected.
Shadowing 隐藏
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/02
*/
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}/**Output:
x = 23
this.x = 1
ShadowTest.this.x = 0
*///~
序列化:
内部类的序列化是强烈劝阻的,包括本地内部类和匿名内部类。
Lambda表达式: 用来优美地实例化只有一个方法的类。
Lambda 表达式看上去更像是一个方法的声明,可以把Lambda表达式当成匿名方法,一个没有名字的方法。
Lambda表达式语法:
- 包含在花括号内逗号分隔的正常参数。
- 箭头符号 ->
- 主体,包含简单的表达式或者语句块
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/03
*/
public class Calculator {
interface IntegerMath {
int operation(int a, int b);
}
public int operateBinary(int a, int b, IntegerMath op) {
return op.operation(a, b);
}
public static void main(String... args) {
Calculator myApp = new Calculator();
IntegerMath addition = (a, b) -> a + b;
IntegerMath subtraction = (a, b) -> a - b;
System.out.println("40 + 2 = " +
myApp.operateBinary(40, 2, addition));
System.out.println("20 - 10 = " +
myApp.operateBinary(20, 10, subtraction));
}
}/**Output:
40 + 2 = 42
20 - 10 = 10
*///~
方法operateBinary 对两个整型操作数进行算术运算。运算方式是用接口IntegerMath声明的。这个例子用Lambda表达式定义了两种操作,addition 和 subtraction。
如果一个Lambda表达式的目标类型和携带参数都是可序列化的,你可以序列化这个Lambda表达式。然而,就像匿名类,强烈建议别瞎捣腾去序列化Lambda表达式。
枚举类型
枚举类型:是一个允许定义和使用常数集合的特殊类。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
枚举类型有个方法 values() 可以返回包含所有值的数组,并且按照声明的顺序。
for(Day d : Day.values()) {
//...
}
package helloworldapp;
/**
* @author linyk001
* @date 2018/08/03
*/
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);
private final double mass; // in kilograms
private final double radius; // in meters
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() { return mass; }
private double radius() { return radius; }
// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;
double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Planet <earth_weight>");
System.exit(-1);
}
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight/EARTH.surfaceGravity();
for (Planet p : Planet.values())
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}/** Output:传入的参数是111时
Your weight on MERCURY is 41.931095
Your weight on VENUS is 100.454900
Your weight on EARTH is 111.000000
Your weight on MARS is 42.039827
Your weight on JUPITER is 280.891885
Your weight on SATURN is 118.327725
Your weight on URANUS is 100.469119
Your weight on NEPTUNE is 126.354416
*/// ~
注解
参考译文
注解是一种元数据的形式,为编译器提供信息。
注解不是程序本身,仅提供程序相关的信息,注解对它们所注释的代码没有直接的影响。
这里介绍在哪里以及怎样高效的在程序中使用注解。
注解的用途:
- Information for the compiler:为编译器提供信息来检测错误或者抑制警告。
- Compile-time and deployment-time processing: 编译时和发布时处理,软件工具可以处理注解信息来生成代码,XML文件等等。
- Runtime processing,运行时处理,一些注解可以在运行时进行检查。
注解基础
注解的格式:
符号@
告诉编译器这接下来的是一个注解。
@Entity
@Override
void mySuperMethod() { ... }
@Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
class MyClass() { ... }
or
@SuppressWarnings(value = "unchecked")
void myMethod() { ... }
//如果只有一个元素叫做value,那这个名字可以被省略
@SuppressWarnings("unchecked")
void myMethod() { ... }
@Author(name = "Jane Doe")
@Author(name = "John Smith")
class MyClass { ... }
可以使用注解的地方:
注解可以用在声明:声明类,域,方法和其他程序元素。当注解用在声明时,一般是单独一行。
Java SE8 发布后,注解可以用在类型:
//Class instance creation expression: 创建类的实例
new @Interned MyObject();
//Type cast:类型强制转换
myString = (@NonNull String) str;
//implements clause:实现子句
class UnmodifiableList<T> implements
@Readonly List<@Readonly T> { ... }
//Thrown exception declaration:抛异常声明
void monitorTemperature() throws
@Critical TemperatureException { ... }
声明一个注解类型
许多注解用来替换代码中的注释。
一般类中的注释信息:
public class Generation3List extends Generation2List {
// Author: John Doe
// Date: 3/17/2002
// Current revision: 6
// Last modified: 4/12/2004
// By: Jane Doe
// Reviewers: Alice, Bill, Cindy
// class code goes here
}
要用注解来加上同样的元数据,我们首先需要定义一个注解类型:
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
String lastModified() default "N/A";
String lastModifiedBy() default "N/A";
// Note use of array
String[] reviewers();
}
定义注解的方式有点类似定义接口,使用了关键字interface
和前缀@
符号,注解是属于接口的一种。
定义好注解后,就可以使用注解了:
@ClassPreamble (
author = "John Doe",
date = "3/17/2002",
currentRevision = 6,
lastModified = "4/12/2004",
lastModifiedBy = "Jane Doe",
// Note array notation
reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {
// class code goes here
}
Note: To make the information in
@ClassPreamble
appear in Javadoc-generated documentation, you must annotate the@ClassPreamble
definition with the@Documented
annotation:
为了@ClassPreamble
的信息可以出现在javadoc文档生成中,需要在定义中加上@Documented
注解
// import this to use @Documented
import java.lang.annotation.*;
@Documented
@interface ClassPreamble {
// Annotation element definitions
}
预定义注解类型
一系列的注解类型在Java SE API中预定义了。一些注解类型被用在Java编译器,一些被用在其他注解上。
Java语言中用到的注解
java.lang
中预定义的注解类型是:
- @Deprecated:弃用
表示已经被弃用,当程序使用了@Deprecated注解标注的方法/类/域时,编译器会发出警告。
@Override: 覆盖
告诉编译器这个元素是覆盖父类的一个元素声明@SuppressWarnings:抑制警告
告诉编译器抑制原本会产生的特定的警告。
// use a deprecated method and tell
// compiler not to generate a warning
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
// deprecation warning
// - suppressed
objectOne.deprecatedMethod();
}
上面例子中,调用了一个被弃用的方法,正常编译器会提示警告,但是加了@SuppressWarning
后,这个警告就被抑制了。
抑制多种警告信息:
@SuppressWarnings({"unchecked", "deprecation"})
@SafeVarargs 安全参数
运用在方法或构造器上,表明代码不会对参数进行潜在的不安全的操作。@FunctionalInterface 函数式接口
表示声明的类型是Java SE 8中的函数式接口
被其他注解应用的注解
被其他注解应用的注解成为元注解。
这里有一些元注解定义在java.lang.annotation
-
@Retention 保留注解
表明标记的注解是怎么保存的:- RetentionPolicy.SOURCE 只保留在源码中,编译器会忽略它
- RetentionPolicy.CLASS 编译时被编译器保留,但是被JVM忽略
- RetentionPolicy.RUNTIME 被JVM保留所以能在运行时环境使用
@Documented Java 文档
表明被标记的注解要被javadoc工具记录。 Javadoc tools page.
-
@Target 目标
限制被标记的注解能被哪种Java 元素应用。- ElementType.ANNOTATION_TYPE can be applied to an annotation type.
- ElementType.CONSTRUCTOR can be applied to a constructor.
- ElementType.FIELD can be applied to a field or property.
- ElementType.LOCAL_VARIABLE can be applied to a local variable.
- ElementType.METHOD can be applied to a method-level annotation.
- ElementType.PACKAGE can be applied to a package declaration.
- ElementType.PARAMETER can be applied to the parameters of a method.
- ElementType.TYPE can be applied to any element of a class.
@Inherited 继承
表示被标记的注解类型可以从父类中继承。这个注解只用在类的声明。@Repeatable 可重复的
Java SE8 中@Repeatable
注解表明被标记的注解可以被应用多次在同一个声明或类型使用上。
Type注解和插件
在Java 8之前,注解仅仅只能在声明(declarations)时使用。在Java 8,注解可以在任何 type use。这就是说,注解可以应用在任何你使用type的地方。例如,class实例的创建表达式(new),类型转换(casts),implements子句,throws子句。这种注解被称为type annotation。更多例子,可以参考上面的基础知识(Annotations Basics)。
Type annotation是为了提高Java程序的强类型检查功能而诞生的。Java 8并没有提供一个类型检查框架(type checking framework),但却允许你自己写(或者down)一个类型检查框架作为Java编译器的插件使用。
举个例子,你想确保你程序里的某些变量永远不会被赋值为null;你想避免产生NullPointerException。你可以自己写个插件来检查。你只需要修改你的代码,把特定变量加上标识不能用null赋值的注解。这个变量的声明可能看起来像这样:
@NonNull String str;
重复注解
Java SE 8 开始,可以使用重复注解
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }
接口和继承
接口是什么,为什么使用接口,怎样使用接口
从基类继承,生成一个导出类。子类和父类的关系
所有的类都是继承自Obeject
类
Numbers和Strings
Number 和 String 类的使用,以及格式化输出
泛型
泛型是Java语言中一个强大的特性,提升了代码的类型安全,使得代码bug能在编译阶段检测得到
包
包能够帮助你组织构造生成的类以及其他类之间的关系。