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
        • 泛型

官方文档

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 语言

  1. Lambda 表达式
  2. 方法引用提供了易读的 lambda 表达式
  3. 接口类的方法提供 default 实现
  4. 重复注解,相同注解可标注多次(java.lang.annotation.Repeatable)
  5. 类型注解(ElementType.TYPE_PARAMETER, ElementType.TYPE_USE)
  6. 改进类型引用
  7. 方法参数反射

2. 集合

  1. java.util.stream 包中的类提供了 Stream API ,支持 对流元素的函数风格操作.
  2. hash key 碰撞性能提升

3. javac

The javac compiler has a -profile option

4. Security

  1. 客户端默认开启 TLS 1.2
  2. 新增AccessController.doPrivileged(PrivilegedExceptionAction action, AccessControlContext context, Permission... perms) throws PrivilegedActionException 能够代码断言 特权的子集,不用遍历stack去校验其他权限.
  3. 更强大的密码加密算法
  4. SSL/TLS Server Name Indication (SNI) Extension support in JSSE Server(不懂)
  5. 支持 AEAD 算法
  6. KeyStore 增强,
  7. SHA-224 Message Digests
  8. 支持 NSA Suite B Cryptography
  9. 更好的支持高级加密随机数字生成.
  10. 新增 java.security.cert.PKIXRevocationChecker 类配置 废弃X.509证书校验
  11. 支持 windows系统 64-bit PKCS11
  12. 新的等级类型-(Kerberos 是由 MIT 设计的一个安全认证协议, )
  13. 支持 Kerberos 5 协议转换和受限委派
  14. 默认关闭 Kerberos 5 弱密码加密类型
  15. 无约束的简单认证与安全层(SASL)
  16. 多主机的SASL service
  17. JNI bridge to native JGSS on Mac OS X
  18. Support for stronger strength ephemeral DH keys in the SunJSSE provider
  19. Support for server-side cipher suites preference customization in JSSE

5. JavaFX

  1. 深紫色主题实现
  2. SwingNode 类允许开发者在 JavaFX 应用中嵌入 Swing
  3. 新的UI控制: DatePicker and the TreeTableView
  4. javafx.print 包提供了打印API
  5. 支持 3D Graphics 特性
  6. WebView 类提供了新特性和改进
  7. 增强 text 支持
  8. 支持 Hi-DPI displays
  9. CSS Styleable 类成功公共API
  10. ScheduledService 类允许重启服务
  11. JavaFX 可在 ARM 平台使用.

6.Tools

  1. jjs 命令调用Nashorn 引擎(一种JavaScript 引擎,已废弃)
  2. java 命令可启动 javaFX 应用
  3. java命令手册已经重写
  4. jdeps 命令分析类文件
  5. Java Management Extensions (JMX) 提供对 诊断命令的远程访问.
  6. The jarsigner tool has an option for requesting a signed time stamp from a Time Stamping Authority (TSA).

7. Internationalization

  1. 支持 Unicode 6.2.0
  2. Adoption of Unicode CLDR Data and the java.locale.providers System Property
  3. 新的 Calendar and Locale APIs
  4. 安装 Custom Resource Bundle 作为扩展

8. Deployment

  1. 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.
  2. The Permissions attribute is required in the JAR file manifest of the main JAR file at all security levels.
  3. Date-Time Package - a new set of packages that provide a 全面的 date-time model.

9. Scripting

Nashorn Javascript Engine 替代 Rhino javascript engine

10. Pack200

  1. Pack200 支持常量池和字节码(JSR 292)
  2. JDK8 支持的类文件已经修改(JSR-292, JSR-308 and JSR-335 声明的那些类文件)

11.IO and NIO

  1. 为 Solaris 提供 新的SelectorProvider 实现
  2. 减少 /jre/lib/charsets.jar 包大小
  3. java.lang.String(byte[], *) constructor and thejava.lang.String.getBytes()method 性能提升

12. java.lang and java.util Packages

  1. Parallel Array Sorting
  2. Standard Encoding and Decoding Base64
  3. 支持 无符号算术

13. JDBC

  1. 移除 JDBC-ODBC Bridge
  2. JDBC 4.2 介绍了新特性

14. Java DB

JDK 8 包含了 Java DB 10.10.

15. Networking

  1. 新增 java.net.URLPermission
  2. java.net.HttpURLConnection类中,如果安装了 security manager ,那么需要权限才能调用请求

16.Concurrency

  1. java.util.concurrent包新增了类和接口
  2. java.util.concurrent.ConcurrentHashMap新增了方法支持 聚集操作
  3. java.util.concurrent.atomic 新增类
  4. java.util.concurrent.ForkJoinPool新增方法支持 common pool
  5. '新增 java.util.concurrent.locks.StampedLock

17.Java XML - JAXP

18. HotSpot

  1. 硬件内部函数新增 AES ,使用 选项开启.
-XX:+UseAES -XX:+UseAESIntrinsics
  1. 移除PermGen,永久代

  2. 方法调用字节码指令 支持 默认方法.

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 编程语言提供了以下几种变量:

  1. 实例变量 Instance Variables (Non-Static Fields)
    成员变量(无 static 关键字修饰)

  2. 类变量 Class Variables (Static Fields)
    static 关键字修饰的 成员变量

  3. 本地变量 Local Variables
    方法内部声明的变量

  4. 参数变量 Parameters
    方法的参数变量

命名

变量名:以字母,$ 符号或下划线(_) 开头.首字母之后的字符可以是字母.数字,$_

变量名最好用全称,别用简写!

一个单词的变量名使用全部小写;第2个单词和以后的单词的首字母需要大写,其余小写;
常量多个字母间使用下划线(_)拼接,所有字母大写.

基本数据类型

  1. byte
    8-bit, 取值范围 -128 到 127(包含127) ( -2的 7次方 到 2的 7次方-1)

  2. short
    16-bit,2个字节, 取值范围- 32,768 到 32,767 (包含32767)

  3. int
    32-bit , 4个字节, 取值范围 -2的 31次方 到 2的 31次方-1

  4. long
    64-bit , 8个字节, 取值范围 -2的 63次方 到 2的 63次方-1

  5. float
    单精度浮点类型,32-bit (如果需要更高精度,则 可使用 java.math.BigDecimal 替换)

  6. double
    双精度浮点类型,64-bit(如果需要更高精度,则 可使用 java.math.BigDecimal 替换)

  7. boolean
    true 或 false

  8. 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 工具类提供了操作数组的方法,比如:

  1. binarySearch 方法查找元素
  2. equals 比较两个数组
  3. fill 使用特定值填充数组每个元素
  4. sort按升序排列数组
  5. stream 使用流遍历处理数组
java.util.Arrays.stream(copyTo).map(coffee -> coffee + " ").forEach(System.out::print);  
  1. 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: 同一注解可以在同一位置可以标注多个

接口与继承

数值与String

泛型