Java 8 学习记录
Java 8 学习记录
目录- Java 8 学习记录
- 官方文档
- API 文档地址
- 新特性
- 1. Java 语言
- 2. 集合
- 3. javac
- 4. Security
- 5. JavaFX
- 6.Tools
- 7. Internationalization
- 8. Deployment
- 9. Scripting
- 10. Pack200
- 11.IO and NIO
- 12. java.lang and java.util Packages
- 13. JDBC
- 14. Java DB
- 15. Networking
- 16.Concurrency
- 17.Java XML - JAXP
- 18. HotSpot
- JDK 和 JRE 关系
- Java 语言
- 面向对象编程概念(Object-Oriented Programming Concepts)
- 1. 什么是对象?
- 2. 什么是类?
- 3. 什么是继承?
- 4. 什么是接口?
- 5. 什么是包?
- Java语言基础
- 变量
- 命名
- 基本数据类型
- 数组
- Java的关键字
- 操作符
- 表达式,语句和代码块
- 流程控制
- 类和对象
- 类
- 内部类
- 对象
- 枚举类型
- 注解
- 接口与继承
- 数值与String
- 泛型
- 包
- 面向对象编程概念(Object-Oriented Programming Concepts)
官方文档
https://docs.oracle.com/javase/8/
https://docs.oracle.com/javase/8/docs/index.html
https://docs.oracle.com/javase/tutorial/index.html
API 文档地址
https://docs.oracle.com/javase/8/docs/api/
新特性
1. Java 语言
- Lambda 表达式
- 方法引用提供了易读的 lambda 表达式
- 接口类的方法提供 default 实现
- 重复注解,相同注解可标注多次(java.lang.annotation.Repeatable)
- 类型注解(ElementType.TYPE_PARAMETER, ElementType.TYPE_USE)
- 改进类型引用
- 方法参数反射
2. 集合
- java.util.stream 包中的类提供了 Stream API ,支持 对流元素的函数风格操作.
- hash key 碰撞性能提升
3. javac
The javac compiler has a -profile option
4. Security
- 客户端默认开启 TLS 1.2
- 新增
AccessController.doPrivileged(PrivilegedExceptionAction
能够代码断言 特权的子集,不用遍历stack去校验其他权限.action, AccessControlContext context, Permission... perms) throws PrivilegedActionException - 更强大的密码加密算法
- SSL/TLS Server Name Indication (SNI) Extension support in JSSE Server(不懂)
- 支持 AEAD 算法
- KeyStore 增强,
- SHA-224 Message Digests
- 支持 NSA Suite B Cryptography
- 更好的支持高级加密随机数字生成.
- 新增
java.security.cert.PKIXRevocationChecker
类配置 废弃X.509证书校验 - 支持 windows系统 64-bit PKCS11
- 新的等级类型-(Kerberos 是由 MIT 设计的一个安全认证协议, )
- 支持 Kerberos 5 协议转换和受限委派
- 默认关闭 Kerberos 5 弱密码加密类型
- 无约束的简单认证与安全层(SASL)
- 多主机的SASL service
- JNI bridge to native JGSS on Mac OS X
- Support for stronger strength ephemeral DH keys in the SunJSSE provider
- Support for server-side cipher suites preference customization in JSSE
5. JavaFX
- 深紫色主题实现
- SwingNode 类允许开发者在 JavaFX 应用中嵌入 Swing
- 新的UI控制: DatePicker and the TreeTableView
- javafx.print 包提供了打印API
- 支持 3D Graphics 特性
- WebView 类提供了新特性和改进
- 增强 text 支持
- 支持 Hi-DPI displays
- CSS Styleable 类成功公共API
- ScheduledService 类允许重启服务
- JavaFX 可在 ARM 平台使用.
6.Tools
jjs
命令调用Nashorn 引擎(一种JavaScript 引擎,已废弃)java
命令可启动 javaFX 应用java
命令手册已经重写jdeps
命令分析类文件- Java Management Extensions (JMX) 提供对 诊断命令的远程访问.
- The jarsigner tool has an option for requesting a signed time stamp from a Time Stamping Authority (TSA).
7. Internationalization
- 支持 Unicode 6.2.0
- Adoption of Unicode CLDR Data and the java.locale.providers System Property
- 新的 Calendar and Locale APIs
- 安装 Custom Resource Bundle 作为扩展
8. Deployment
- For sandbox applets and Java Web Start applications, URLPermission is now used to allow connections back to the server from which they were started. SocketPermission is no longer granted.
- The Permissions attribute is required in the JAR file manifest of the main JAR file at all security levels.
- Date-Time Package - a new set of packages that provide a 全面的 date-time model.
9. Scripting
Nashorn Javascript Engine 替代 Rhino javascript engine
10. Pack200
- Pack200 支持常量池和字节码(JSR 292)
- JDK8 支持的类文件已经修改(JSR-292, JSR-308 and JSR-335 声明的那些类文件)
11.IO and NIO
- 为 Solaris 提供 新的SelectorProvider 实现
- 减少
/jre/lib/charsets.jar 包大小 java.lang.String(byte[], *)
constructor and thejava.lang.String.getBytes()
method 性能提升
12. java.lang and java.util Packages
- Parallel Array Sorting
- Standard Encoding and Decoding Base64
- 支持 无符号算术
13. JDBC
- 移除 JDBC-ODBC Bridge
- JDBC 4.2 介绍了新特性
14. Java DB
JDK 8 包含了 Java DB 10.10.
15. Networking
- 新增
java.net.URLPermission
类 - 在
java.net.HttpURLConnection
类中,如果安装了 security manager ,那么需要权限才能调用请求
16.Concurrency
java.util.concurrent
包新增了类和接口java.util.concurrent.ConcurrentHashMap
新增了方法支持 聚集操作java.util.concurrent.atomic
新增类java.util.concurrent.ForkJoinPool
新增方法支持 common pool- '新增
java.util.concurrent.locks.StampedLock
类
17.Java XML - JAXP
18. HotSpot
- 硬件内部函数新增 AES ,使用
-XX:+UseAES -XX:+UseAESIntrinsics
-
移除PermGen,永久代
-
方法调用字节码指令 支持 默认方法.
JDK 和 JRE 关系
关系图如下:
原图地址:https://docs.oracle.com/javase/8/docs/index.html
Java 语言
面向对象编程概念(Object-Oriented Programming Concepts)
1. 什么是对象?
对象是理解面向对象技术的关键.
真实世界的对象有2个特征: 状态(state)和行为(behavior).
软件对象和真实世界对象很相似.都是由2部分组成: state 和 关联的behavior.
对象使用 field 存储state , 通过 methods 暴露行为, Methods 操作 对象内部的state,服务于对象之间的通信,
如下图:
2. 什么是类?
Object 是class 的一个实例.类是从对象中抽象出来的.将许多对象的共同的属性(state) 和方法()抽取出来形成1个 class.
class Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
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);
}
}
3. 什么是继承?
面向对象编程允许一个类去继承另一个类的state and behavior 去使用.每个 类只能有1个父类,每个父类可以有多个子类.
继承是通过关键字extends
实现的.
// MountainBike 继承了 Bicycle
class MountainBike extends Bicycle {
// new fields and methods defining
// a mountain bike would go here
}
4. 什么是接口?
接口就是相关的方法(没有方法体)集合.
interface Bicycle {
// wheel revolutions per minute
void changeCadence(int newValue);
void changeGear(int newValue);
void speedUp(int increment);
void applyBrakes(int decrement);
}
实现接口通过关键字 implements
体现.
// ACMEBicycle 实现了 Bicycle 接口
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);
}
}
接口形成了类与外界的连接,这种连接在构建时期由编译器执行.一个类如果实现接口,那么接口里的所有方法必须实现.
Java 8 支持接口类中的方法提供默认实现.
5. 什么是包?
包是组织一组相关类和接口的命名空间.类似于电脑上的文件夹.
Java 8 API 文档:https://docs.oracle.com/javase/8/docs/api/index.html
Java语言基础
变量
Java 编程语言提供了以下几种变量:
-
实例变量 Instance Variables (Non-Static Fields)
成员变量(无 static 关键字修饰) -
类变量 Class Variables (Static Fields)
static 关键字修饰的 成员变量 -
本地变量 Local Variables
方法内部声明的变量 -
参数变量 Parameters
方法的参数变量
命名
变量名:以字母,$
符号或下划线(_
) 开头.首字母之后的字符可以是字母.数字,$
或 _
变量名最好用全称,别用简写!
一个单词的变量名使用全部小写;第2个单词和以后的单词的首字母需要大写,其余小写;
常量多个字母间使用下划线(_
)拼接,所有字母大写.
基本数据类型
-
byte
8-bit, 取值范围 -128 到 127(包含127) ( -2的 7次方 到 2的 7次方-1) -
short
16-bit,2个字节, 取值范围- 32,768 到 32,767 (包含32767) -
int
32-bit , 4个字节, 取值范围 -2的 31次方 到 2的 31次方-1 -
long
64-bit , 8个字节, 取值范围 -2的 63次方 到 2的 63次方-1 -
float
单精度浮点类型,32-bit (如果需要更高精度,则 可使用java.math.BigDecimal
替换) -
double
双精度浮点类型,64-bit(如果需要更高精度,则 可使用java.math.BigDecimal
替换) -
boolean
true 或 false -
char
16-bit Unicode 字符,\u0000
到\uffff
默认值
数组
下图是有10个元素的数组
声明一个数组:
// declares an array of integers
int[] anArray;
实例化一个数组:
int[] anArray = new int[10];
实例化一个数组,并初始化元素值
int[] anArray = {1,2,3,4,5,6,7,8,9,10};
拷贝数组:
class ArrayCopyDemo {
public static void main(String[] args) {
String[] copyFrom = {
"Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",
"Doppio", "Espresso", "Frappucino", "Freddo", "Lungo", "Macchiato",
"Marocchino", "Ristretto" };
String[] copyTo = new String[7];
System.arraycopy(copyFrom, 2, copyTo, 0, 7);
for (String coffee : copyTo) {
System.out.print(coffee + " ");
}
}
}
遍历数组:
class ArrayCopyOfDemo {
public static void main(String[] args) {
String[] copyFrom = {
"Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",
"Doppio", "Espresso", "Frappucino", "Freddo", "Lungo", "Macchiato",
"Marocchino", "Ristretto" };
String[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9);
for (String coffee : copyTo) {
System.out.print(coffee + " ");
}
}
}
java.util.Arrays
工具类提供了操作数组的方法,比如:
binarySearch
方法查找元素equals
比较两个数组fill
使用特定值填充数组每个元素sort
按升序排列数组stream
使用流遍历处理数组
java.util.Arrays.stream(copyTo).map(coffee -> coffee + " ").forEach(System.out::print);
toString
将数组转为 String
Java的关键字
- abstract
- continue
- for
- new
- switch
- assert***(added in 1.4)
- default
- goto*(not used)
- package
- synchronized
- boolean
- do
- if
- private
- this
- break
- double
- implements
- protected
- throw
- byte
- else
- import
- public
- throws
- case
- enum****(added in 5.0)
- instanceof
- return
- transient
- catch
- extends
- int
- short
- try
- char
- final
- interface
- static
- void
- class
- finally
- long
- strictfp**(added in 1.2)
- volatile
- const* (not used)
- float
- native
- super
- while
注意:
*
not used
**
added in 1.2
***
added in 1.4
****
added in 5.0
操作符
图片地址:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
表达式,语句和代码块
表达式 是由 变量,操作符和方法调用组成.
(x + y) / 100 // unambiguous, recommended
语句 : 完整的执行单元,以分号结尾的
表达式语句:
// assignment statement
aValue = 8933.234;
// increment statement
aValue++;
// method invocation statement
System.out.println("Hello World!");
// object creation statement
Bicycle myBike = new Bicycle();
代码块:由一组大括号包含的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
}
}
流程控制
- if-then-else
- switch ( 1.7 开始,支持String)
public static int getMonthNumber(String month) {
int monthNumber = 0;
if (month == null) {
return monthNumber;
}
switch (month.toLowerCase()) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
case "april":
monthNumber = 4;
break;
case "may":
monthNumber = 5;
break;
case "june":
monthNumber = 6;
break;
case "july":
monthNumber = 7;
break;
case "august":
monthNumber = 8;
break;
case "september":
monthNumber = 9;
break;
case "october":
monthNumber = 10;
break;
case "november":
monthNumber = 11;
break;
case "december":
monthNumber = 12;
break;
default:
monthNumber = 0;
break;
}
return monthNumber;
}
}
- while 和 do ... while
while (expression) {
statement(s)
}
do {
statement(s)
} while (expression);
- for 循环
for (initialization; termination;
increment) {
statement(s)
}
class EnhancedForDemo {
public static void main(String[] args){
int[] numbers =
{1,2,3,4,5,6,7,8,9,10};
for (int item : numbers) {
System.out.println("Count is: " + item);
}
}
}
- break (跳出循环)
- continue(跳过本次循环,继续下次循环)
- return(返回)
// 有返回值方法
return ++count;
// void 方法
return;
类和对象
类
声明一个类:
/*
修饰符 class关键字 类名 extends 父类名 implements 接口名(多个){
}
*/
class MyClass extends MySuperClass implements YourInterface {
// field, constructor, and
// method declarations
}
声明成员变量:
// 访问修饰符 类型 变量名
public int cadence;
public int gear;
public int speed;
定义方法:
/*
访问修饰符 返回值 方法名(参数类型 参数名, ...){
}
*/
public double calculateAnswer(double wingSpan, int numberOfEngines,
double length, double grossTons) {
//do the calculation here
}
方法重载:
Java 可以通过方法签名判断方法是否不同,Java 支持一个类中存在方法名相同,参数列表不同的方法.参数列表不同的含义是:方法参数类型不同 或者 方法参数个数不同
// 存在多个重载方法的draw 方法
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) {
...
}
}
注意:尽量克制使用方法重载,过多的使用会降低可读性.
构造器
一个类可以包含多个构造器,构造器在创建类的一个对象时被调用.
如果不声明构造器,那么编译器会自动生成一个无参的构造器.
构造器和普通方法很像,但是,构造器不能有返回类型且构造器名必须和类名一致!
/*
修饰符 类名(参数列表...){
构造器方法体
}
*/
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
任意数量的参数
// polygonFrom方法有任意数量且类型为Point的变量
public Polygon polygonFrom(Point... corners) {
int numberOfSides = corners.length;
double squareOfSide1, lengthOfSide1;
squareOfSide1 = (corners[1].x - corners[0].x)
* (corners[1].x - corners[0].x)
+ (corners[1].y - corners[0].y)
* (corners[1].y - corners[0].y);
lengthOfSide1 = Math.sqrt(squareOfSide1);
// more method body code follows that creates and returns a
// polygon connecting the Points
}
基本类型参数传递的是具体值;引用类型传递的是引用地址.
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;
}
}
类成员变量的访问级别
有2种类型的访问级别:
- 类的访问级别: public 或者 默认(只能同一个包内类访问)
- 成员的访问级别: public, private,protected 或者默认(只能同一个包内类可访问)
理解类 成员
- 类变量: static 修饰的成员变量
- 类方法: static 修饰的方法
- 类方法可直接访问类变量和类方法.
- 类方法不能直接访问非static成员变量和非static方法,只能通过
对象.方法
访问.
常量
// 常量命名:字母必须全部大写,且多个单词用下划线连接
static final double PI = 3.141592653589793;
初始化成员
public class BedAndBreakfast {
// initialize to 10
public static int capacity = 10;
// initialize to false
private boolean full = false;
}
静态初始化块
多个静态初始化块,按声明的先后顺序进行初始化.
static {
// whatever code is needed for initialization goes here
}
或者
class Whatever {
public static varType myVar = initializeClassVariable();
private static varType initializeClassVariable() {
// initialization code goes here
}
}
初始化块
java 编译器,将初始化块复制到每个构造器中
{
// whatever code is needed for initialization goes here
}
final 方法:
class Whatever {
private varType myVar = initializeInstanceVariable();
// final 方法,不能被子类重写
protected final varType initializeInstanceVariable() {
// initialization code goes here
}
}
内部类
class OuterClass {
...
// 内部类
class InnerClass {
...
}
// 静态内部类
static class StaticNestedClass {
...
}
}
内部类 实例化:
// 先实例化外部类,再实例化内部类
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
OuterClass.java
public class OuterClass {
String outerField = "Outer field";
static String staticOuterField = "Static outer field";
class InnerClass {
void accessMembers() {
System.out.println(outerField);
System.out.println(staticOuterField);
}
}
static class StaticNestedClass {
void accessMembers(OuterClass outer) {
// Compiler error: Cannot make a static reference to the non-static
// field outerField
// System.out.println(outerField);
System.out.println(outer.outerField);
System.out.println(staticOuterField);
}
}
public static void main(String[] args) {
System.out.println("Inner class:");
System.out.println("------------");
OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
innerObject.accessMembers();
System.out.println("\nStatic nested class:");
System.out.println("--------------------");
StaticNestedClass staticNestedObject = new StaticNestedClass();
staticNestedObject.accessMembers(outerObject);
System.out.println("\nTop-level class:");
System.out.println("--------------------");
TopLevelClass topLevelObject = new TopLevelClass();
topLevelObject.accessMembers(outerObject);
}
}
public class TopLevelClass {
void accessMembers(OuterClass outer) {
// Compiler error: Cannot make a static reference to the non-static
// field OuterClass.outerField
// System.out.println(OuterClass.outerField);
System.out.println(outer.outerField);
System.out.println(OuterClass.staticOuterField);
}
}
内部类的序列化强烈不推荐使用.
本地类
可以在任意一个代码块中,声明一个类.
public class LocalClassExample {
static String regularExpression = "[^0-9]";
public static void validatePhoneNumber(
String phoneNumber1, String phoneNumber2) {
final int numberLength = 10;
// Valid in JDK 8 and later:
// int numberLength = 10;
class PhoneNumber {
String formattedPhoneNumber = null;
PhoneNumber(String phoneNumber){
// numberLength = 7;
String currentNumber = phoneNumber.replaceAll(
regularExpression, "");
if (currentNumber.length() == numberLength)
formattedPhoneNumber = currentNumber;
else
formattedPhoneNumber = null;
}
public String getNumber() {
return formattedPhoneNumber;
}
// Valid in JDK 8 and later:
// public void printOriginalNumbers() {
// System.out.println("Original numbers are " + phoneNumber1 +
// " and " + phoneNumber2);
// }
}
PhoneNumber myNumber1 = new PhoneNumber(phoneNumber1);
PhoneNumber myNumber2 = new PhoneNumber(phoneNumber2);
// Valid in JDK 8 and later:
// myNumber1.printOriginalNumbers();
if (myNumber1.getNumber() == null)
System.out.println("First number is invalid");
else
System.out.println("First number is " + myNumber1.getNumber());
if (myNumber2.getNumber() == null)
System.out.println("Second number is invalid");
else
System.out.println("Second number is " + myNumber2.getNumber());
}
public static void main(String... args) {
validatePhoneNumber("123-456-7890", "456-7890");
}
}
匿名类
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
public void sayHello() {
class EnglishGreeting implements HelloWorld {
String name = "world";
public void greet() {
greetSomeone("world");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hello " + name);
}
}
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
HelloWorld spanishGreeting = new HelloWorld() {
String name = "mundo";
public void greet() {
greetSomeone("mundo");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hola, " + name);
}
};
englishGreeting.greet();
frenchGreeting.greetSomeone("Fred");
spanishGreeting.greet();
}
public static void main(String... args) {
HelloWorldAnonymousClasses myApp =
new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
匿名内部类访问外部类本地变量限制(https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html#accessing):
- 匿名内部类,可以访问所在类的成员变量;
- 匿名内部类不能访问本地变量(没有
final
关键字修饰的变量); - 匿名内部类声明的变量,覆盖外部内相同名字的变量;
- 匿名内部类不能声明静态初始化方法或静态成员接口(You cannot declare static initializers or member interfaces in an anonymous class).
- 匿名内部类可以有静态常量;
- 不能再匿名内部类中声明构造器
Lambda表达式
语法:
// 格式: 小括号包围的逗号分隔的参数列表 + "->" + 方法体
// Java 会自动评估返回值
p -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
// 或者
// p 代表方法参数类型的实例,下面示例的方法只有1个参数
p -> {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
注:不推荐序列化 lambda表达式.
lambda方法引用 4种类型:
什么时候使用内部类,本地类,匿名类,Lambda表达式?
链接:https://docs.oracle.com/javase/tutorial/java/javaOO/whentouse.html
本地类:当创建一个类的多个实例,访类的构造方法.
匿名内部类:如果需要声明成员变量或额外的方法时使用.
lambda表达式:(1) 当你想将单一的行为传给其他代码去执行 (2) 创建函数接口简单实例时
内部类:和本地类需求一样,但是不要求访问外部类的本地变量和方法参数
对象
创建对象:
Point originOne = new Point(23, 94);
创建对象语句,包含了3部分:
(1) 声明变量:比如上边的 Point originOne.
(2) 实例化对象: new
关键字是创建对象的操作符.
- 给对象分配内存,并返回内存地址的引用.
(3) 初始化对象: new
操作符后紧跟着调用构造器方法进行初始化对象.
垃圾回收
一些面向对象语言要求你跟踪对象,当对象不再使用的时候进行销毁.
Java 允许你创建足够的对象,不用担心销毁他们,Java 运行环境当发现对象不再使用时,自动删除对象,这样的过程叫垃圾回收.
垃圾收集器自动回收释放对象占用的空间.
枚举类型
enum 类型是一个特殊的数据类型,能够让变量预定义一些常量集合.
enum 类型成员是大写字母.
// 简单枚举
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
测试:
public class EnumTest {
Day day;
public EnumTest(Day day) {
this.day = day;
}
public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY: case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}
public static void main(String[] args) {
EnumTest firstDay = new EnumTest(Day.MONDAY);
firstDay.tellItLikeItIs();
EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
thirdDay.tellItLikeItIs();
EnumTest fifthDay = new EnumTest(Day.FRIDAY);
fifthDay.tellItLikeItIs();
EnumTest sixthDay = new EnumTest(Day.SATURDAY);
sixthDay.tellItLikeItIs();
EnumTest seventhDay = new EnumTest(Day.SUNDAY);
seventhDay.tellItLikeItIs();
}
}
// 带构造器枚举类
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 ");
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));
}
}
注解
注解,元数据(我理解是一个配置信息)的一种形式,提供关于程序的数据,但注解并不属于程序.
Annotations 有很多用途,:
- 给编译器提供信息,编译器可通过注解发现错误和禁止警告.
- 编译时期和部署时期处理:软件工具可以根据注解生成代码,xml文件.
- 运行时期处理:一些注解能够在运行时期检查.
注解用在哪里?
- 注解应用于声明:类,成员变量,方法和其他程序元素.
- JAVA 8 支持注解应用在类型使用的地方,比如:
- 创建类实例表达式
new @Interned MyObject();
- 类型匹配
myString = (@NonNull String) str;
- 接口实现
class UnmodifiableList
implements @Readonly List<@Readonly T> { ... } - 异常抛出
void monitorTemperature() throws @Critical TemperatureException { ... }
声明一个注解
@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();
}
@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
}
Java 提供的预定义注解
- @Deprecated : 标记的元素已经过时,不再维护
- @Override : 通知编译器此元素重写父类的元素.
- @SuppressWarnings :告诉编译器去禁止特定的警告
- @SafeVarargs:应用于方法或构造器
- @FunctionalInterface : 表明类型为函数接口类型
元注解
Java 提供的标注在其他注解上的注解
- @Retention: 表示标记的注解怎么存储,
- RetentionPolicy.SOURCE 注解仅保留在原代码上,编译器会忽略
- RetentionPolicy.CLASS:注解保留在编译阶段,JVM会忽略
- RetentionPolicy.RUNTIME: 注解保留在JVM中,在运行环境中可以使用
- @Documented : 表示改注解将在Java Doc 中保留
- @Target : 注解标注的位置
- ElementType.ANNOTATION_TYPE: 可以标注在注解上
- ElementType.CONSTRUCTOR:可以标注在构造器上
- ElementType.FIELD:可以标注在成员变量上
- ElementType.LOCAL_VARIABLE: 可以标注在本地变量上
- ElementType.METHOD : 可以标注在方法上
- ElementType.PACKAGE: 可以标注在包上
- ElementType.PARAMETER:可以标注在方法参数上
- ElementType.TYPE:可以标注在类的任意元素上
- @Inherited:子类可以从父类上标注的注解继承
- @Repeatable: 同一注解可以在同一位置可以标注多个