文章目录
1. 第一个 Java 程序
打开终端,输入
$ vim HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
ystem.out.println("Hello world!"); // static提供了这样一个特性,无需建立对象,就可以启动
}
}
在终端将上述代码存放到 Hello.java
中,使用 javac Hello.java
编译代码,生成一个 Hello.class
文件,接着使用 java Hello
来运行程序。
Java 源程序与编译型运行区别
基础语法
- 对大小写敏感
- 类名应当大写开头
- 方法名要小写开头
- 源文件名要和类名相同
- 标识符由字母、下划线或 $ 打头,不能是关键字
2. Java 对象和类
看一个简单的类:
public class Dog {
String name; // 实例变量
String color;
int age;
// 构造器 public
public Dog(String name, int age, String color) {
this.name = name; // 参数名和实例变量名相同时,使用 this
this.age = age;
this.color=color;
}
public void run() {
System.out.println(name + " is running...");
}
public int gerAge() {
System.out.println("Age: " + age);
return age;
}
public static void main(String[] args) {
// 创建对象
Dog myDog = new Dog("Tom", 2, "Brown");
System.out.println(myDog.color);
myDog.gerAge();
myDog.run();
}
}
这个类描述了小狗,属性包含:名字、颜色和年龄,类里面的函数称为方法。
类中包含了一个 static 的静态方法 public static void main(String[] args)
,不需要对象调用,可以自动执行。
this
关键字:
当实例变量和局部变量重名,JAVA平台会按照先局部变量、后实例变量的顺序寻找。
如果使用 this.name
,则不会在方法(局部变量)中寻找变量name,而是直接去实例变量中去寻找。
当实例变量和局部变量名字不重复时,可以不使用 this,编译器会自动加上 this
2.1 构造器
一般构造函数 public 可加可不加。如果加上 public,就代表此类可以对外开放,其他的类可以继承它,外部也可以实例化该对象;如果不加 public,则默认的修饰词是protected,代表只对同包开放。
2.2 创建对象和访问实例
Dog tom = new Dog("Tom"); // 使用关键字 new 创建对象
tom.color // 访问属性
tome.run(); // 访问方法
2.3 Java 包
import java.io.* // 导入java_installation/java/io下的所有类
3. 数据与变量
3.1 基本数据类型
public class Data{
public static void main(String[] args){
int a = 65;
short b = 0;
float c = 2.5;
int d = 100; // decimal
int e = 054; // octal
int f = 0x30; // hex
char ch = 'a';
String str = "Hello";
boolean full = false;
byte a1 = (byte)a; // 强制转换
final double PI = 3.1459265; // const
// 可以查看特定类型数据的长度和范围
System.out.println(Integer.MAX_VALUE);
System.out.println(Double.SIZE);
}
}
Java 为每一个内置数据类型都提供了对应的包装类
:Boolean, Byte, Short, Integer, Long, Character, Float, Double.
public class Test{
public static void main(String[] args){
Double x = 5.3;
System.out.println(Math.floor(x));
}
}
Java Math
类:
public class Test{
public static void main(String[] args){
System.out.println("PI = " + Math.PI);
System.out.println("cos(PI/2) = " + Math.tan(Math.PI/4));
System.out.println("random: " + Math.random());
System.out.println("exp()")
}
}
3.2 基本变量类型
- 类变量:独立于方法之外的变量,用 static 修饰;
- 实例变量:独立于方法之外的变量,不过没有 static 修饰;
- 局部变量:类的方法中的变量。
public class Var{
static int count = 0; // 类变量
String str = "Tom"; // 实例变量
public void method(){
int i = 0; // 局部变量
}
}
类变量属于静态变量,无论一个类有多少个对象,类变量都共用一个!
4. Java 修饰符
4.1 访问控制修饰符
Java 支持四种不同的访问权限:
default:在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
4.2 非访问修饰符
static
静态变量:static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。
静态函数:static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。
public class INstenceCOunter{
private static int numInstences = 0; // 静态变量
prvate static void addInstence(){ // 静态函数
numInstences++;
}
}
注意:在静态方法中调用非静态方法时,编译器会报错(因为非静态方法只有实例化的对象能够调用,而静态方法执行的过程中未调用构造函数实例化对象,因此不允许调用!)
解决办法可以参考 博客 ,要么创建一个类的对象,通过对象来调用函数,要么将非静态方法声明中加上 static
改为静态方法,同时将变量声明为全局静态的。
final
被 final 修饰的实例变量必须显式指定初始值,之后不能再修改
public class Test{
final double PI = 3.14159; // 不能修改值
// final 方法不能被子类重写
public final void changeName(String name){
this.name = name;
}
}
5. 程序的逻辑结构
常见循环结构如下:
while (true){
count--;
if (count == 0)
break;
}
for (int i=0; i<n; i++){
count--;
}
String [] names = {"Tom", "Domy", "Sam"};
for (String name : names){
System.out.print(name + " ");
}
常用的分支结构如下:
if (a == 1)
return 1;
else if (a == 0)
return -1;
else
return 0;
switch (expression){
case value1:
pass;
case value2:
pass;
default: // not match with any value
pass;
}
6. String 字符串
6.1 字符串的存储
public class CharacterClass {
public static void main(String[] args) {
String str1 = "12345"; // 公共池
String str2 = "12345";
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
String str3 = new String("12345"); // 堆
String str4 = new String("12345");
System.out.println(System.identityHashCode(str3));
System.out.println(System.identityHashCode(str4));
}
}
函数 System.identityHashCode(str)
可以打印出字符串 str 地址对应的哈希值
使用 String str = "xxxxx";
声明的字符串存储在公共池里,存储字符串内容相同的字符串变量相当于引用;
使用 new String("xxxx");
得到的字符串地址在堆内,每次 new
得到的对象地址不同;
110718392
110718392
231685785
114935352
6.2 字符串相关函数
长度 length()
// 长度 str.length()
String site = "blog.csdn.net";
int siteLength = site.length();
System.out.println("Length = " + siteLength);
格式化字符串 String.format(str, args)
String 类使用静态方法 format() 返回一个String 对象
// String.format(str, args)
String str = String.format("int a = %d, " + "float b = %f", 5, 5.2);
System.out.println(str);
字符索引查询 indexOf()
int pos1 = "abcdacd".indexOf('a'); // 0
int pos1 = "abcdacd".indexOf('k'); // -1
int pos2 = "abcdacd".lastIndexOf('a'); // 4
字符串分割 split()
String [] res1 = "abcdefghijklmnopqr".split("g");
String [] res2 = "abcdefghijklmnopqr".split("f|m");
子串 substring()
// public String substring(int beginIndex, int endIndex=-1)
String string = "this is text";
System.out.println(string.substring(2, 7));
比较函数 equals
填补一个大坑:equals
比较的是内容是否相等、==
比较的是引用的变量地址是否相等。
String str1 = new String("xxx");
String str2 = new String("xxx");
System.out.println(str1.equals(str2));
7. StringBuffer 和 StringBuilder 类
7.1 特点
StrngBuilder 和 StringBuffer 类的对象支持多次的 增删改查
,而且并且不产生新的未使用对象!
- StringBuilder 的方法不是线程安全的,但速度高(不能同步访问)。
- 由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
7.2 StringBuilder 和 StringBuffer 的使用
常用函数的语法如下(StringBuilder 和 StringBuffer 的使用方法几乎相同):
StringBuilder sb = new StringBuilder(int capacity); // 创建对象
// 与 string 相同的函数
public int length()
public StringBuilder(int capacity)
public String substring(int beginIndex, int endIndex)
// 修改内容
public StringBuilder append(char[] str) // 追加字符串
public StringBuilder insert(int index, char[] str) // 在 index 插入 str
public StringBuilder delete(int start, int end) // 删除 [start, end)
public StringBuilder replace(int start, int end, String str) // 将 [start, end) 的内容用 str 替换
public synchronized StringBuffer reverse() // StringBuffer reverse
举个例子:
public class StringB {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(10);
sb.append("Runoob..");
System.out.println(sb);
sb.append("!");
System.out.println(sb);
sb.insert(8, "Java");
System.out.println(sb);
sb.delete(5, 8);
System.out.println(sb);
}
}
输出的结果为,具体可以参考 菜鸟教程:
Runoob..
Runoob..!
Runoob..Java!
RunooJava!
8. 数组的使用
声明与创建:
int[] myList; // declare
myList = new int[10]; // 创建
int arraySize = 10;
double myList = new double[arraySize];
int[][] a = new int[3][4]; // 多维数组
int[] a = {0, 1, ..., n}; // 初始化
数组的访问与修改:
import java.lang.reflect.Array;
public class ArrayTest {
// reveerse array element
public static int[] reverseArray(int[] list) {
int[] res = new int[list.length];
for (int i=0; i<list.length; i++) {
res[i] = list[list.length-1 - i];
}
return res;
}
public static void main(String[] args) {
int size = 10;
int[] array = new int[size];
for (int i=0; i<array.length; i++) {
array[i] = i*i;
}
int[] reversedArray = reverseArray(array);
for (int elem : reversedArray) {
System.out.print(elem + " ");
}
}
}
// 81 64 49 36 25 16 9 4 1 0
可以使用 Arrays
类的函数来对数组操作:
public static void sort(Object[] a) // 排序
public static int binarySearch(Object[] a, Object key) // 在有序数组中折半查找
举个例子:
import java.util.Arrays;
public class ArrayTest {
public static void main(String[] args) {
int size = 5;
double[] array = new double[size];
for (int i=0; i<array.length; i++) {
array[i] = Math.random();
}
Arrays.sort(array);
for (double elem : array) {
System.out.println(elem);
}
}
}
9. Java 方法
9.1 方法的定义与调用
一个方法包含了 修饰符
、返回值类型
、方法名
、参数
和 方法体
构成
在不创建类对象的情况下,主函数可以调用静态方法:
public class MethodTest {
public static int max(int a, int b) {
return a > b ? a : b;
}
public static void main(String[] args) {
int a = 2;
int b = 5;
System.out.println(max(a, b));
}
}
9.2 可变参数
可变参数的声明方式为:
typeName... parameterName
举个例子:
public class Test{
public static void main(String[] args){
System.out.println(sum(1, 2, 3, 4, 5)); // 15.0
}
public static double sum(double... list){
double res = 0;
for (double elem : list){
res += elem;
}
return res;
}
}
此处传入的参数有很多个,可以像数组一样来访问传入的参数。
10. 时间和日期
10.1 查看时间
java.util
包提供了 Date 类来封装当前的日期和时间,可以 new 一个 Date 对象:
import java.util.Date;
public class Test{
public static void main(String[] args){
Date date = new Date(); // 初始化对象
System.out.println(date.toString());
}
}
10.2 格式化输出时间
import java.util.Date;
import java.text.SimpleDateFormat;
public class Test{
pblic static void main(String[] args){
// 创建 Date 对象
Date currTime = new Date();
// 设置格式
SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss yyyy/MM/dd E");
// 格式化输出
System.out.println("Current time: " + ft.format(currentTime));
}
}
10.3 测量时间
Thread.sleep(1000)
休眠 1000ms
System.currentTimeMillis()
获取毫秒数
import java.util.Date;
try {
// 获取从1970年1月1号0时0分0秒至今的毫秒数
long start = System.currentTimeMillis();
System.out.println(new Date().toString());
// 休眠 3 s
Thread.sleep(3000);
System.out.println(new Date().toString());
long end = System.currentTimeMillis();
long diff = start - end;
System.out.println(diff + " msec");
} catch (Exception e) {
System.out.println("Got an exception!");
}
10.4 Calendar 类
import java.util.Calendar;
public class Test1 {
public static void main(String[] args) {
Calendar c1 = Calendar.getInstance();
System.out.println(c1.getTime());
System.out.println(c1.get(Calendar.YEAR));
System.out.println(c1.get(Calendar.MONTH));
System.out.println(c1.get(Calendar.DATE));
}
}
11. 输入与输出
11.1 Scanner 类
Java 提供了 Scannner
类,可以设置参数来从键盘读取数据,创建Scanner
对象如下:
import java.util.Scanner;
Scanner scan = new Scanner(System.in); // 参数 System.in 代表读取键盘的输入
11.2 读取字符串
输入字符串的方式有两种:
next()
- 一定要读取到有效字符后才可以结束输入
- 输入一行时,以空格分隔字符串,因此不能得到带有空格的字符串;
nextLine()
- 输入一行,以换行符结束,能读取有空格的字符串
- 可以读取空白内容
举个例子:(输入为 “hello world”)
import java.util.Scanner;
public class Test{
public static void main(String[] args){
Scanner sc1 = new Scanner(System.in);
System.out.println(sc1.next()); // hello
Scanner sc2 = new Scanner(System.in);
System.out.println(sc2.nextLine()); // hello world
}
}
11.3 读取数字
下面的程序对输入的所有数字求和,当输入不是 double 类型时(如字符串),程序会终止
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double sum = 0;
while (sc.hasNextDouble()) {
sum += sc.nextDouble();
}
sc.close();
System.out.println("Sum: " + sum);
}
}
12. 异常捕获
使用 try-catch
来捕获 异常:
try{
double c = 3/0;
} catch (Exception e){
System.out.println("Got an error: " + e); // 打印错误
} finally{
System.out.println("This statement is excuted!");
}
可以有多个 catch
来捕获不同类型的错误;不论是否存在异常,finall
关键字中的语句都会被执行。
输出结果为:
Got an error: java.lang.ArithmeticException: / by zero
This statement is excuted!
13. data structure
Java 提供了一系列的存储数据结构和相应的算法,各种容器由 Collections
继承而来,算法可以通过 Collections
类来调用;容器的创建方法如下:
import java.util.ContainerName; // 引入容器类
ContainerName<E> objectName =new ContainerName<E>(); // 初始化
13.1 ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制;
package dataStructure;
import java.util.ArrayList;
import java.util.Collections;
public class dataStructure {
public static void main(String[] args) {
ArrayList<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(5);
myList.add(2);
myList.add(6);
myList.add(4);
myList.remove(0);
for (Integer i : myList) {
System.out.print(i + " ");
}
System.out.println();
Collections.sort(myList);
// Collections.reverse(myList);
for (Integer i : myList) {
System.out.print(i + " ");
}
}
}
13.2 Stack
Stack
常用的方法有:boolean empty()
, E push()
, E pop()
, E peek()
package dataStructure;
import java.util.Stack;
public class dataStructure {
public static void main(String[] args) {
Stack<Integer> s = new Stack<Integer>();
s.push(1); // 压栈
s.push(2);
s.push(3);
s.push(4);
s.push(5);
Integer a = s.peek(); // 访问栈顶
System.out.println(a);
Integer sum = 0;
while(!s.empty()) { // 判空
sum += s.pop(); // 弹栈
}
System.out.println(sum);
}
}
除此之外,Java 还有 Vector
, LinkList
, Queue
, Dictionary
等常用容器,可以通过查看手册或查看源码来学习使用!