1 Java 概述
2014 Java8
2017 Java9
Java11 LTS版
2 Java 程序设计环境
2.1 Java 术语
-
JDK: Java开发工具(包含JRE)
-
JRE: Java运行环境
-
Java SE (Standard Edition) 标准版本:用于桌面或者简单服务器应用的Java平台
-
Java EE (Enterprise Edition) 企业版本:用于复杂服务器应用的Java平台
-
Java ME (Micro Edition) 微型版本:用于小型设备的Java平台
-
NetBeans:Oracle公司的集成开发环境
2.2 命令行工具编译运行
javac 是一个 Java 编译器,将文件 Welcome.java 编译成 Welcome.class,java 程序启动 Java 虚拟机,虚拟机执行类文件中的字节码
javac Welcome.java
java Welcome
注意:
java Welcome
,java 区分大小写- javac 需要文件名(Welcome.java),而运行程序时,只需指定类名,不需要带扩展名
.java
或.class
常见错误及解决方法:
https://docs.oracle.com/javase/tutorial/getStarted/problems/index.html
2.3 JShell
Java 9 以上,交互式窗口
那么何时开始使用IDE工具呢?标准是:如果你还离不开这个IDE工具,那么你就不能使用这个IDE工具;只有当你十分清楚在IDE工具里单击每一个菜单,单击每一个按钮……IDE工具在底层为你做的每个细节时,才可以使用IDE工具!
3 Java 基本程序设计
3.1 简单结构
public class FirstSample {
public static void main(String[] args){
System.out.println("Hello World!");
}
}
注意:
- Java 区分大小写
- Java 类名必须以字母开头,后面跟字母和数字的组合,长度基本没有限制,但不能用 Java 保留字。采用驼峰命名法(camel case),CamelCase
- 源代码文件名必须与公共类名字相同,并用
.java
为拓展名 - main 方法必须声明为 public
3.2 注释
//
/**/
以/**开头,*/结束,多用于类的注释
3.3 数据类型
强类型语言,8中基本类型
3.3.1 整型
类型 | 字节数 | 取值范围 |
---|---|---|
int | 4 | -2147483648~2147483647(刚超过20亿) |
short | 2 | -32 768~32 767 |
long | 8 | -9223372036854775808~9223372036854775807 |
byte | 1 | -128~127 |
- long 类型后面有一个后缀 L 或 l (40000000L)。十六进制 0x 或 0X。八进制前缀 0
- Java 7 开始加上前缀 0b 或 0B 可以写二进制数。另外还可以为数字变量加上下划线,如 1_000_000 表示 100 万
3.3.2 浮点类型
类型 | 字节数 | 有效位数 |
---|---|---|
float | 4 | 6~7位 |
double | 8 | 15位 |
-
float 类型后有一个后缀 F 或 f ,没有后缀的浮点数值默认为 double 类型
-
三个特殊的浮点数值:
正无穷大、负无穷大、NaN(不是一个数字)
Double.POSITIVE_INFINITY、Double.NEGATIVE_INFINITY、Double.NaN分别表示这三个特殊值
注意判断时不能直接 == ,使用Double.isNaN
方法判断 -
浮点值不适用于无法接受舍入误差的金融计算
如,System.out.println(2.0-1.1)
将打印出 0.8999999999999999 而不是 0.9,这是因为浮点数值采用二进制系统表示,在其中无法精确地表示分数 1/10,对于这种情况换用BigDecimal
类
3.3.3 char 类型
最好不要使用这种类型
1个java的char字符并不完全等于一个unicode的字符。char采用的UCS-2编码,是一种淘汰的UTF-16编码,编码方式最多有65536种,远远少于当今Unicode拥有11万字符的需求。java只好对后来新增的Unicode字符用2个char拼出1个Unicode字符。导致String中char的数量不等于unicode字符的数量。
3.3.4 boolean 类型
boolean 只有两个值 true 和 false
- java中 true != 1,false != 0
3.4 变量与常量
Java 10 开始,可以使用 var 关键字而无需指定类型
var a = 12;
var c = "hello";
3.4.1 常量
用 final
指示常量,表示这个常量只能被赋值一次。习惯上,常量名使用全大写。
3.4.2 枚举类型
public enum Size {SMALL, MEDIUM, LARGE}
3.5 运算符
3.6 字符串
字符串用双引号括起来
-
子串
String greeting = "Hello"; String s = greeting.substring(0, 3);//左闭右开思想
-
拼接
String message = "Hello" + "World";
连在一起,用界定符分隔,用
join
方法:String all = String.join("/", "S", "M", "L", "XL"); // all is string "S/M/L/XL"
Java 11 还提供了一个 repeat 方法:
String repeated = "Java".repeat(3); // "JavaJavaJava"比较字符串是否相等
-
判断字符串相等
"Hello".equals(greeting);
-
构建字符串
StringBuilder builder = new StringBuilder();//Java5+ builder.append(ch); builder.append(str); String myString = builder.toString();
3.7 输入与输出
3.7.1 读取输入
首先构造一个与 System.in 相关联的 Scanner 对象,然后使用 Scanner 对象的方法进行读取
Scanner 对象属于 java.util 包,不属于 java.lang 包的,都需要 import
import java.util.*;
/**
* This program demonstrates console input.
* @version 1.10 2004-02-10
* @author Cay Horstmann
*/
public class InputTest
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
// get first input
System.out.print("What is your name? ");
String name = in.nextLine();
// get second input
System.out.print("How old are you? ");
int age = in.nextInt();
// display output on console
System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1));
}
}
Java 6 引入 Console 类读取密码:
Console cons = System.console();
String username = cons.readLine("Username: ");
char[] passwd = cons.readPassword("Password: ");//安全起见,返回密码存放在字符数组中。密码处理完成后,应马上用一个填充值覆盖字符数组元素
3.7.2 格式化输出
System.out.print 和 C 语言的语法差不多
格式化打印时间:
System.out.printf("%tc", new Date());
//周六 8月 08 18:12:27 CST 2020
Y 年 m 月 d 日 H 时 M 分 S 秒
一个参数可被多次使用,添加索引方式,索引必须以 %
开头,以 $
结束
System.out.printf("%1$s %2$tB %2$tm, %2$tY", "Due date: ", new Date());
//Due date: 八月 08, 2020
也可以使用 <
知识前面的参数将被再次使用
System.out.printf("%s %tB %<tm, %<tY", "Due date: ", new Date());
3.7.3 文件输入输出
3.8 大数
BigInteger 和 BigDecimal 可以分实现任意精度的整数和浮点数的计算
valueof 方法将普通的数值转化成大数:
BigInteger a = BigInteger.valueOf(100);
不能使用算法运算符(+和*)处理大数,而需要使用 add 和 multipy 方法
4 对象与类
4.1 访问控制符
- private —— 仅对本类可见
- public —— 对外部完全可见
- protected —— 对本包和所有子类可见
- 默认,不需要修饰符 —— 对本包可见
4.2 包
用命令行编译运行带包的 java 文件层,需要在上一层且带上包名
javac inheritance\ManagerTest.java
java inheritance.ManagerTest
5 继承
5.1 类,超类和子类
已存在的类被称为超类(superclass)、基类(base class)或父类(parent class);新类被称为子类(subclass)、派生类(derived class)或孩子类(child class)
package com.horstmann.corejava;
// the classes in this file are part of this package
import java.time.*;
// import statements come after the package statement
/**
* @version 1.11 2015-05-08
* @author Cay Horstmann
*/
public class Employee
{
private String name;
private double salary;
private LocalDate hireDay;
public Employee(String name, double salary, int year, int month, int day)
{
this.name = name;
this.salary = salary;
hireDay = LocalDate.of(year, month, day);
}
public String getName()
{
return name;
}
public double getSalary()
{
return salary;
}
public LocalDate getHireDay()
{
return hireDay;
}
public void raiseSalary(double byPercent)
{
double raise = salary * byPercent / 100;
salary += raise;
}
}
public class Manager extends Employee{
……
}
覆盖方法
public double getSalary(){
double baseSalary = super.getSalary();
//不能直接用salary,因为它在Employee类中是private的
return baseSalary+bonus;
}
子类构造器
public Manager(String name, double salary, int year, int month, int day){
super(name, salary, year. month, day);
bonus = 0;
}
5.1.1 阻止继承:final 类和方法
阻止派生 Executive 类的子类
public final class Executiv extends Manager{
……
}
同样设置方法为 final ,子类就不可以覆盖这个方法
public class Employee{
public final String getName(){
return name;
}
}
5.1.2 抽象类
抽象类声明抽象的方法,具体实现是在子类。抽象类方便方法调用。
package abstractClasses;
public abstract class Person
{
public abstract String getDescription();
private String name;
public Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
public class Student extends Person
{
public String getDescription()
{
return "a student majoring in " + major;
}
}
5.2 Object:所有类的超类
可以用 Object 类型变量引用任何类型的对象。具体操作时需要进行强制类型转换
Object obj = new Employee("Hacker", 3500);
Employee e = (Employee)obj;
只有基本类型不是对象,所有数组类型,包括基本类型的数组都拓展了 Object 类
5.3 泛型数组列表
Java 中允许在运行中确定数组的大小,更简单的方法是使用 ArrayList 类,类似于数组,但在添加或删除元素的时候,能自动调整数组容量。
尖括号中类型参数不允许是基本类型
ArrayList<Employee> staff = new ArrayList<Employee>();
//or
ArrayList<Employee> staff = new ArrayList<>();
//java10 可以使用 var
var staff = new ArrayList<Employee>();
staff.add(new Employee("Hacker",...));
staff.set(i, harry);
Employee e = staff.get(i);
5.4 反射
https://javasec.org/javase/Reflection/Reflection.html
6 接口、lambda 表达式与内部类
6.1 接口
接口不是类,而是对希望符合这个接口的类的一组需求。
Comparable 接口代码:
public interface Comparable<T>{
int compareTo(T other);
}
在接口中所有方法都自动是 public,不过在实现的时候,必须把方法声明为 public
public class Employee implements Comparable<Employee>
{
/**
* Compares employees by salary
* @param other another Employee object
* @return a negative value if this employee has a lower salary than
* otherObject, 0 if the salaries are the same, a positive value otherwise
*/
public int compareTo(Employee other)
{
return Double.compare(salary, other.salary);
}
}
为什么不把接口设计为抽象类呢?
一个类智能继承一个类但能实现多个接口。
Java 设计者选择了不支持多重继承,因为其会让语言变得非常复杂或者降低效率。
6.2 lambda 表达式
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
package lambda;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
/**
* This program demonstrates the use of lambda expressions.
* @version 1.0 2015-05-12
* @author Cay Horstmann
*/
public class LambdaTest
{
public static void main(String[] args)
{
var planets = new String[] { "Mercury", "Venus", "Earth", "Mars",
"Jupiter", "Saturn", "Uranus", "Neptune" };
System.out.println(Arrays.toString(planets));
System.out.println("Sorted in dictionary order:");
Arrays.sort(planets);
System.out.println(Arrays.toString(planets));
System.out.println("Sorted by length:");
Arrays.sort(planets, (first, second) -> first.length() - second.length());
System.out.println(Arrays.toString(planets));
var timer = new Timer(1000, event ->
System.out.println("The time is " + new Date()));
timer.start();
// keep program running until user selects "OK"
JOptionPane.showMessageDialog(null, "Quit program?");
System.exit(0);
}
}
6.3 代理
动态代理(Dynamic Proxy)的机制:可以在运行期动态创建给定接口的新类。
https://javasec.org/javase/DynamicProxy/DynamicProxy.html
7 异常处理
https://www.runoob.com/java/java-exceptions.html