0%

Java基础大全

一、 Java变量

  • 局部变量:存储在方法的栈内存中
    • 形参
    • 方法内的局部变量
    • 代码块的局部变量
    • 无法用static修饰
  • 类变量(静态变量):用static修饰的变量,调用时使用类名.变量名(static可以修饰方法名)
  • 成员变量(非静态变量)
1
2
3
4
public class RightDef {
int num1 = num2 + 5; // 静态变量无需考虑声明的位置
static int num2 = 20; // 静态变量
}

二、Java访问控制权限

private default protected public
同一类 y y y y
同一包内的类 y y y
子类 y y
其他包内的类 需要继承 y

三、Java源程序与编译型运行区别

四、程序控制

4.1 循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 第一种
while(){

}

// 第二种
do{

}while();

// 第三种
for(初始化;布尔表达式;更新){

}

// Foreach语法,用于数组和容器
for(float x : f){ // f是数组或容器
System.out.println(x);
}

4.2 条件

1
2
3
4
5
6
7
8
9
10
11
if(){
if(){

}
else if(){

}
}
else{

}

4.3 选择

1
2
3
4
5
6
7
8
9
switch(expression){
case value1: //语句
break;
case value2: // 语句
break;
default: // 语句
break;
}

五、数组

5.1 概念

  • 数组属于引用数据类型
  • 包含:数组名、下标、元素

5.2 特点

  1. 数组是有序排列的
  2. 数组属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型
  3. 创建数组对象会在内存中开辟一整块连续的空间
  4. 数组的长度一旦确定,就不能修改

5.3 操作

1
2
3
4
5
6
7
8
9
10
11
12
13
int[] ids;  //数组声明
ids = new int[]{1,2,3}; //静态初始化,初始化同时进行赋值,new int[]不能省略
int[] ids = {1,2,3};

//动态初始化,初始化与元素赋值分开
String[] names = new String[5];

// 获取数组长度
int len = ids.length;

// 数组元素的调用
names[0] = "zs";
names[1] = "ls";

5.4 数组元素的默认初始化值

  • 整型:0
  • 浮点型:0
  • char:0或’\u0000’,而非’0’
  • boolean:false
  • 数组元素是引用数据类型时:null

5.5 多维数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 二维数组静态初始化
int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
int[] arr1[] = new int[][]{{1,2,3},{4,5},{6,7,8}};
int[] arr1[] = {{1,2,3},{4,5},{6,7,8}};

// 动态初始化1
String[][] arr2 = new String[3][2];

// 动态初始化2
String[][] arr2 = new String[3][];
System.out.println(arr2[1][0]); //由于没有初始化,所以会报空指针异常

arr2[1] = new String[4]; // 给arr[1]初始化后,再来输出就不会报错
System.out.println(arr2[1][0]);

// 错误形式
// int[][] arr3 = new int[4][3]{{1,2,3},{4,5},{6,7,8}}

5.5.1 多维数组的默认初始值

1
2
3
4
int[][] arr = new int[4][3];
System.out.println(arr[0]); // 地址值
System.out.println(arr[0][0]); // null

5.6 数组的遍历

1
2
3
4
5
// foreach方式
int[] a = new int[]{1,2,3}
for(int element:a)
System.out.println(element);

5.7 Array类

5.7.1 常用方法

  • java.util.Array类的所有方法均为静态方法
  • boolean equals(int[] a,int[] b):判断两个数组是否相等
  • String toString(int[] a):输出数组信息
  • void fill(int[] a,int val):将指定值填充到数组中
  • void sort(int[] a):对数组进行排序(快速排序)
  • int binarySearch(int[] a,int key):对排序后的数进行二分法检索指定的值

5.8 数组常见异常

  • 空指针:NullPointerException
  • 数组下标越界:ArrayIndexOutOfBoundsException

六、类和对象

6.1 类

6.1.1 构造器

  • 一个在创建对象时被自动调用的特殊方法
  • 名称必须要和类名相同
  • 构造器调用顺序是客->主
  • 每个类都有构造方法,没有显示的为类定义构造方法,Java编译器会提供一个默认的构造方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Rock2{
    Rock(int i){
    System.out.print("Rock"+i+" ");
    }
    }

    public class SimpleConstructor2(){
    public static void main(String args[]){
    for(int i=0;i<8;i++)
    new Rock2(i);
    }
    }

    // Rock 0 Rock 1 Rock 2 Rock 3 Rock 4 Rock 5 Rock 6 Rock 7

6.1.2 类的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Dog{
String breed;
int age;
String color;
void barking(){
}

void hungry(){
}

void sleeping(){
}
}

6.1.3 类中的变量类型

  • 局部变量
  • 成员变量
  • 类变量

6.2 对象

  • 声明:声明一个对象,包括对象名和对象类型
  • 实例化:使用new来创建一个对象
  • 初始化:new创建对象时,会调用构造函数
1
2
3
4
5
6
7
8
9
10
public class Puppy{
public Puppy(String name){
//这个构造器仅有一个参数:name
System.out.println("小狗的名字是 : " + name );
}
public static void main(String[] args){
// 下面的语句将创建一个Puppy对象
Puppy myPuppy = new Puppy( "tommy" );
}
}

七、面向对象特性

7.1 封装

  • 创建类以实现现实中抽象事物属性以及方法的封装

7.2 继承

7.2.1 继承的实现

1
2
3
4
5
6
class father{

}
class son extends father{

}

7.2.2 继承的特性

  • 子类拥有父类非private的属性、方法
  • 所有的类都继承于java.lang.Object

7.2.3 Super关键字

  1. 在子类的成员方法中,访问父类的成员变量。
  2. 在子类的成员方法中,访问父类的成员方法。
  3. 在子类的构造方法中,访问父类的构造方法。

7.3 多态

7.3.1 多态实现的必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象

7.3.2 多态的实现方式

  • 重写
  • 接口
  • 抽象类和抽象方法

八、抽象类和抽象方法

8.1 抽象类

  • 抽象类用来描述一种类型应该具备的基本特征与功能,具体如何去完成这些行为由子类通过方法重写来完成
  • 抽象方法指只有功能声明,没有功能主体实现的方法
  • 有抽象方法的类一定是抽象类
  • 抽象类无法直接创建对象,只能被子类继承后,创建子类对象
  • 抽象方法必须被子类重写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public abstract class Employee
{
private String name;
private String address;
private int number;
public Employee(String name, String address, int number)
{
System.out.println("Constructing an Employee");
this.name = name;
this.address = address;
this.number = number;
}
public double computePay()
{
System.out.println("Inside Employee computePay");
return 0.0;
}
public void mailCheck()
{
System.out.println("Mailing a check to " + this.name
+ " " + this.address);
}
public String toString()
{
return name + " " + address + " " + number;
}
public String getName()
{
return name;
}
public String getAddress()
{
return address;
}
public void setAddress(String newAddress)
{
address = newAddress;
}
public int getNumber()
{
return number;
}
}

8.3 抽象方法

  • 抽象方法没有方法体,子类继承后必须重写该方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public abstract class Employee
    {
    private String name;
    private String address;
    private int number;

    public abstract double computePay();

    //其余代码
    }

九、Java接口

9.1 接口与类的区别

  • 接口不能用于实例化对象。
  • 接口没有构造方法。
  • 接口中所有的方法必须是抽象方法。
  • 接口中的成员变量只能是 public static final 类型。
  • 接口不是被类继承了,而是要被类实现。
  • 接口支持多继承

9.2 接口的实现

  • 当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。

  • 类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
interface Animal {
public void eat();
public void travel();
}

public class MammalInt implements Animal{

public void eat(){
System.out.println("Mammal eats");
}

public void travel(){
System.out.println("Mammal travels");
}

public int noOfLegs(){
return 0;
}

public static void main(String args[]){
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}

9.4 接口的特性

  • 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
  • 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
  • 接口中的方法都是公有的。

9.5 接口的继承

  • 一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}

// 文件名: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}

// 文件名: Hockey.java
public interface Hockey extends Sports
{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
  • Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。
  • 相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。

9.6 接口的多继承

  • 在Java中,类的多继承是不合法,但接口允许多继承。

  • 在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:

    1
    public interface Hockey extends Sports, Event

十、Java枚举

10.1 枚举的实现

  • Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。

  • Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    enum Color
    {
    RED, GREEN, BLUE;
    }

    public class Test
    {
    // 执行输出结果
    public static void main(String[] args)
    {
    Color c1 = Color.RED;
    System.out.println(c1);
    }
    }

    // 结果为RED

10.2 迭代枚举元素

1
2
3
4
5
6
7
8
9
10
11
enum Color
{
RED, GREEN, BLUE;
}
public class MyClass {
public static void main(String[] args) {
for (Color myVar : Color.values()) {
System.out.println(myVar);
}
}
}

10.3 枚举中的方法

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
enum Color
{
RED, GREEN, BLUE;
}

public class Test
{
public static void main(String[] args)
{
// 调用 values()
Color[] arr = Color.values();

// 迭代枚举
for (Color col : arr)
{
// 查看索引
System.out.println(col + " at index " + col.ordinal());
}

// 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException
System.out.println(Color.valueOf("RED"));
// System.out.println(Color.valueOf("WHITE"));
}
}

/*结果
RED at index 0
GREEN at index 1
BLUE at index 2
RED
*/

10.4 枚举的作用

  • 封装一组常量
  • 对传入的参数进行约束和限制

十一、Java异常

11.1 异常分类

  1. 检查性异常: 不处理编译不能通过
  2. 非检查性异常:不处理编译可以通过,如果有抛出直接抛到控制台
  3. 运行时异常: 就是非检查性异常
  4. 非运行时异常: 就是检查性异常

所有的异常类是从 java.lang.Exception 类继承的子类

11.2 异常捕获

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 单捕获
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}

// 多异常捕获
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}

11.3 异常抛出

11.3.1 throws关键字

  • 用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,需要由方法的调用者进行异常处理
  • 用在方法声明后面,跟的是异常类名
  • 可以跟多个异常类名,用逗号隔开
  • 表示抛出异常,由该方法的调用者来处理
  • throws表示出现异常的一种可能性,并不一定会发生这些异常

11.3.2 throw关键字

  • 用来抛出一个具体的异常类型。

  • 用在方法体内,跟的是异常对象名

  • 只能抛出一个异常对象名
  • 表示抛出异常,由方法体内的语句处理
  • throw则是抛出了异常,执行throw则一定抛出了某种异常
  • 如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错
  • 执行到 throw 语句则后面的语句块不再执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

package constxiong.interview;

import java.io.IOException;

public class TestThrowsThrow {

public static void main(String[] args) {
testThrows();

Integer i = null;
testThrow(i);

String filePath = null;
try {
testThrow(filePath);
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 测试 throws 关键字
* @throws NullPointerException
*/
public static void testThrows() throws NullPointerException {
Integer i = null;
System.out.println(i + 1);
}

/**
* 测试 throw 关键字抛出 运行时异常
* @param i
*/
public static void testThrow(Integer i) {
if (i == null) {
throw new NullPointerException();//运行时异常不需要在方法上申明
}
}

/**
* 测试 throw 关键字抛出 非运行时异常,需要方法体需要加 throws 异常抛出申明
* @param i
*/
public static void testThrow(String filePath) throws IOException {
if (filePath == null) {
throw new IOException();//运行时异常不需要在方法上申明
}
}
}

11.4 自定义异常类

  • 所有异常都必须是 Throwable 的子类。
  • 如果希望写一个检查性异常类,则需要继承 Exception 类。
  • 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// 文件名InsufficientFundsException.java
import java.io.*;

//自定义异常类,继承Exception类
public class InsufficientFundsException extends Exception
{
//此处的amount用来储存当出现异常(取出钱多于余额时)所缺乏的钱
private double amount;
public InsufficientFundsException(double amount)
{
this.amount = amount;
}
public double getAmount()
{
return amount;
}
}

// 文件名称 CheckingAccount.java
import java.io.*;

//此类模拟银行账户
public class CheckingAccount
{
//balance为余额,number为卡号
private double balance;
private int number;
public CheckingAccount(int number)
{
this.number = number;
}
//方法:存钱
public void deposit(double amount)
{
balance += amount;
}
//方法:取钱
public void withdraw(double amount) throws
InsufficientFundsException
{
if(amount <= balance)
{
balance -= amount;
}
else
{
double needs = amount - balance;
throw new InsufficientFundsException(needs);
}
}
//方法:返回余额
public double getBalance()
{
return balance;
}
//方法:返回卡号
public int getNumber()
{
return number;
}
}

// 下面的 BankDemo 程序示范了如何调用 CheckingAccount 类的 deposit() 和 withdraw() 方法
//文件名称 BankDemo.java
public class BankDemo
{
public static void main(String [] args)
{
CheckingAccount c = new CheckingAccount(101);
System.out.println("Depositing $500...");
c.deposit(500.00);
try
{
System.out.println("\nWithdrawing $100...");
c.withdraw(100.00);
System.out.println("\nWithdrawing $600...");
c.withdraw(600.00);
}catch(InsufficientFundsException e)
{
System.out.println("Sorry, but you are short $"
+ e.getAmount());
e.printStackTrace();
}
}
}

/*Output:
Depositing $500...

Withdrawing $100...

Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
at CheckingAccount.withdraw(CheckingAccount.java:25)
at BankDemo.main(BankDemo.java:13)
*/

十二、Java内部类

12.1 非静态内部类

  • 非静态内部类在类中地位等同于成员变量
  • 非静态内部类实例的创建必须依赖外部类对象
  • 非静态内部类可以访问到外部类的成员变量和成员方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class OuterClass {
private int age = 10;

private class InnerClass{
private int age = 11;
public void print(){
System.out.println(age); //11
System.out.println("内部类提升封装性,代码结构更合理");
}
}

public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
InnerClass innerClass = outerClass.new InnerClass();
innerClass.print();
}
}

12.2 静态内部类

  • 静态内部类使用static对内部类进行标注
  • 静态内部类无法访问外部类的成员变量和成员方法,但可以访问静态成员变量
  • 静态内部类实例无需通过外部类实例进行创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class OuterClass {

private static class InnerClass{
public void print(){
System.out.println("内部类提升封装性,代码结构更合理");
}
}

public void printOuter(){
System.out.println("我是外部类方法");
}

public static void main(String[] args) {
InnerClass innerClass = new OuterClass.InnerClass();
innerClass.print();
}
}

12.3 匿名内部类

  • 不显示声明类继承接口进行方法重写后调用
  • 通过接口引用+匿名内部类在”{}”中重写方法,完成对象实例的创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface MyInterface {
void print();
}

public class NoneClass {
public static void main(String[] args) {
MyInterface myInterface = new MyInterface() {
public void print() {
System.out.println("匿名内部类");
}
};
myInterface.print();
}
}

12.4 使用内部类的原因

  • 内部类提升封装性,隐藏部分操作,代码结构更合理