JAVA方法
方法定义
java
// 方法定义
修饰符 返回值类型 方法名称([参数类型 形参 ...]){
方法体代码;
[return 返回值];
}
方法重载
- 方法名必须相同
- 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
- 与返回值类型是否相同无关
java
public class TestMethod {
public static void main(String[] args) {
add(1, 2); // 调用add(int, int)
add(1.5, 2.5); // 调用add(double, double)
add(1.5, 2.5, 3.5); // 调用add(double, double, double)
}
public static int add(int x, int y) {
return x + y;
}
public static double add(double x, double y) {
return x + y;
}
public static double add(double x, double y, double z) {
return x + y + z;
}
}
递归
- 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同
- 递归出口
java
public static void main(String[] args) {
int n = 5;
int ret = factor(n);
System.out.println("ret = " + ret);
}
public static int factor(int n) {
if (n == 1) {
return 1; //2. 递归出口
}
return n * factor(n - 1); // factor 调用函数自身 1. 将原问题划分成其子问题
}
// 执行结果
ret = 120
JAVA数组的定义与使用
数组的基本概念
java
int[] array1 = new int[10];//1. 动态初始化:在创建数组时,直接指定数组中元素的个数
double[] array2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0};//2. 静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定
int[] array2;//3. 静态和动态初始化也可以分为两步,但是省略格式不可以
array2 = new int[]{10, 20, 30};
如果没有对数组进行初始化,数组中元素有其默认值
| 类型 | 默认值 |
|---|---|
| byte | 0 |
| short | 0 |
| int | 0 |
| long | 0 |
| float | 0.0f |
| double | 0.0 |
| char | /u0000 |
| boolean | false |
数组的使用
java
int[]array = new int[]{10, 20, 30, 40, 50};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
System.out.println(array[4]);
// 也可以通过[]对数组中的元素进行修改
array[0] = 100;
System.out.println(array[0]);
//遍历数组
for(int i = 0; i < 5; i++){
System.out.println(array[i]);
}
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);//在数组中可以通过 数组对象.length 来获取数组的长度
}
for (int x : array) {
System.out.println(x);//使用 for-each 遍历数组
}
二维数组
java
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr[row].length; col++){
System.out.printf("%d\t", arr[row][col]);
}
System.out.println("");
}
// 执行结果
1 2 3 4
5 6 7 8
9 10 11 12
关于一维数组和二维数组快速遍历
一维数组:Arrays.toString(数组)
java
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
// 快速打印!
System.out.println(Arrays.toString(arr));//打印一维数组
}
}
二维数组:Arrays.deepToString(数组)
java
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[][] arr = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 快速打印!
System.out.println(Arrays.deepToString(arr));//deep深度打印二维数组
}
}
JAVA 类和对象
对象的构造及初始化
java
public class Date {
public int year;// 字段(属性) 或者 成员变量
public int month;
public int day;
// 行为 或者 成员方法
public void setDay(int y, int m, int d){
this.year = y;//this引用指向`当前对象`
this.month = m;
this.day = d;
}
public void printDate(){
System.out.println(year + "/" + month + "/" + day);
}
public static void main(String[] args) {
// 构造三个日期类型的对象 d1 d2 d3
Date d1 = new Date();//类的实例化
Date d2 = new Date();
Date d3 = new Date();
// 对d1,d2,d3的日期设置
d1.setDay(2020,9,15);
d2.setDay(2020,9,16);
d3.setDay(2020,9,17);
// 打印日期中的内容
d1.printDate();
d2.printDate();
d3.printDate();
}
}
封装
|访问范围| private(私有) | |
|--|--|
| | |
| 访问范围 | private(私有) | default(默认 / 包访问 | protected(受保护) | public(公共) |
|---|---|---|---|---|
| 同一包中的同一类 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 |
| 同一包中的不同类 | ❌ 不可访问 | ✅ 可访问 | ✅ 可访问 | ✅ 可访问 |
| 不同包中的子类 | ❌ 不可访问 | ❌ 不可访问 | ✅ 可访问 | ✅ 可访问 |
| 不同包中的非子类 | ❌ 不可访问 | ❌ 不可访问 | ❌ 不可访问 | ✅ 可访问 |
static修饰成员变量和方法
【静态成员变量特性】
-
- 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
-
- 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
-
- 类变量存储在方法区当中
-
- 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
【静态方法特性】
-
- 不属于某个具体的对象,是类方法
-
- 可以通过对象调用,也可以通过
类名.静态方法名(...)方式调用,更推荐使用后者
- 可以通过对象调用,也可以通过
-
- 不能在静态方法中访问任何非静态成员变量
-
- 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用
代码块
java
public class haha(){
int a;
public haha(int a){
this.name = name;//实例代码块。构造代码块一般用于初始化实例成员变量
}
}
public static Name = "123";//静态代码块
public static void main(String[] args){
{
int a = 20;//普通代码块:定义在方法中的代码块
System.out.println(a);
}
}
Java继承
java
修饰符 class 子类 extends 父类 {
// ...
}
public class Base {
int a;
int b;
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
int a; // 与父类中成员变量同名且类型相同
char b; // 与父类中成员变量同名但类型不同
// 与父类中methodA()构成重载
public void methodA(int a) {
System.out.println("Derived中的method()方法");
}
// 与基类中methodB()构成重写(即原型一致,重写后序详细介绍)
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
// 对于同名的成员变量,直接访问时,访问的都是子类的
a = 100; // 等价于: this.a = 100;
b = 101; // 等价于: this.b = 101;
// 注意:this是当前对象的引用
// 访问父类的成员变量时,需要借助super关键字
// super是获取到子类对象中从基类继承下来的部分
super.a = 200;
super.b = 201;
// 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
// 如果在子类中要访问重写的基类方法,则需要借助super关键字
methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
super.methodB(); // 访问基类的methodB()
}
}
public class Derived2 extends Base{
public int methodA(){//重写的方法返回值类型可以不同
System.out.println("Derived2中的methodA()");
return 1;
}
}
| 区别点 | 重写 (override,子类重写父类) | 重载 (overload,同一个类内) |
|---|---|---|
| 参数列表 | 一定不能修改(方法名、参数个数 / 类型 / 顺序完全一致) | 必须修改(参数个数、类型、顺序至少一项不同) |
| 返回类型 | 基本不能修改;协变返回类型除外(子类返回值是父类返回值的子类) | 可以随意修改 |
| 访问限定符 | 权限不能更严格(可放宽 / 不变,不能缩小,如父类 public,子类不能用 private) | 可以随意修改 |
| 发生位置 | 父子类之间 | 同一个类内部 |
| 抛出异常 | 不能抛出更宽泛的异常,可抛出更小 / 不抛 | 无限制 |
向上转移和向下转型
java
父类类型 对象名 = new 子类类型()
if(animal2 instanceof Bird){//Java中为了提高向下转型的安全性,引入了 instanceof ,如果该表达式为true,则可以安全转换。
Brid bird2 = (Brid) animal2//向下转型,调用子类特有的方法
}else//报错animal2不是Bird的子类
异常

- Throwable:是异常体系的顶层类,其派生出两个重要的子类, Error 和 Exception
- Error:指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽等,典型代表:StackOverflowError和OutOfMemoryError,一旦发生回力乏术。
- Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。比如:感冒、发烧。我们平时所说的异常就是Exception。
异常的分类
- 编译时异常
在程序编译期间发生的异常,称为编译时异常,也称为受检查异常(Checked Exception) - 运行时异常
在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常(Unchecked Exception)
RunTimeException以及其子类对应的异常,都称为运行时异常
java
try{
// 将可能出现异常的代码放在这里
}catch(要捕获的异常类型 e){
// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类时,就会被捕获到
// 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
}[catch(异常类型 e){
// 对异常进行处理
}finally{
// 此处代码一定会被执行到
}]
// 后序代码
// 当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行
// 如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行
修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2...{//自定义异常类,然后继承自Exception 或者 RunTimeException 实现一个带有String类型参数的构造方法,参数含义:出现异常的原因
...
}
【异常处理流程总结】
- 程序先
执行 try 中的代码 - 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和
catch 中的异常类型是否匹配. - 如果
找到匹配的异常类型, 就会执行 catch 中的代码 - 如果没有找到匹配的异常类型, 就会将
异常向上传递到上层调用者. - 无论是否找到匹配的异常类型,
finally 中的代码都会被执行到(在该方法结束之前执行). - 如果
上层调用者也没有处理的了异常, 就继续向上传递. - 一直到 main 方法也没有合适的代码处理异常, 就会交给
JVM 来进行处理, 此时程序就会异常终止.
java
class UserNameException extends Exception {
public UserNameException(String message) {
super(message);
}
}
class PasswordException extends Exception {
public PasswordException(String message) {
super(message);
}
}
java
public class LogIn {
private String userName = "admin";
private String password = "123456";
public static void loginInfo(String userName, String password)throws UserNameException,PasswordException{//throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常。
if (!userName.equals(userName)) {
throw new UserNameException("用户名错误!");
} if(!password.equals(password)) {
throw new PasswordException("用户名错误!");
}
System.out.println("登陆成功");
}
public static void main(String[] args) {
try {
loginInfo("admin", "123456");
} catch (UserNameException e) {
e.printStackTrace();
} catch (PasswordException e) {
e.printStackTrace();
}
}
}