Java基础学习笔记整合

题记:在大一学过C语言课程,达到浅尝辄止的水平。2021年寒假下定决心要学一学Java,本着提高编程思维、个人兴趣的牵引和以后可能会往这方面就业的心理,自学近20天。

初识

Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承指针等概念,因此Java语言具有功能强大和简单易用两个特征。

Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。

Java具有简单性、面向对象、分布式健壮性安全性、平台独立与可移植性、多线程、动态性等特点 [2] 。Java可以编写桌面应用程序Web应用程序分布式系统嵌入式系统应用程序等。

三大体系

  • Java SE(J2SE)
  • Java ME(J2ME)
  • Java EE(J2EE)

开发

Eclipse、IDEA

编写代码规范

强制性代码规范

  • Java 程序的文件名与类名必须一致以通过编译

  • main 方法是程序的入口,方法的定义必须严格按照格式书写

  • 类是组织 Java 代码结构的,类中的方法是执行具体业务

非强制性代码规范

  • 一行只写一条语句。

  • 注意代码缩进

注释

描述解释,方便自己和他人阅读理解程序

  • 单行注释:
//注释内容
  • 多行注释:
/*注释内容
注释内容
注释内容
*/
  • 文档注释:
/**注释内容
*注释内容
*注释内容
*/

关键字

Java 语言预先定义好的,有指定意义的标识符,组成程序的基本元素。

关键字含义
bstract表示抽象
boolean基本数据类型
break跳出循环
byte基本数据类型
case与 switch 搭配使用
catch与 try 搭配使用,表示捕获异常
char基本数据类型
class表示一个类
continue跳出循环
do与 while 搭配使用,表示循环
double基本数据类型
else与 if 搭配,流程控制
enum枚举类型
extends继承
final修饰常量
float基本数据类型
if流程控制
implements实现接口
import引入某个类
int基本数据类型
nterface表示接口
ong基本数据类型
ative表示本地方法
ackage表示包
rivate私有
ublic共有
eturn返回值
hort基本数据类型
tatic表示静态
uper表示父类
witch与 case 搭配使用
ynchronized线程同步
this表示当前实例
throw抛出异常
throws方法中主动抛出异常
try与 catch 搭配使用
void表示方法没有返回值
volatile保证线程读取到最新值
while表示循环

变量

要素:数据类型、变量名、变量值

变量使用

  • 声明变量的数据类型和变量名(包含数字、字母、下划线、$,不能包含空格、运算符,不能用关键字命名,不能以数字开头),大小写可以混用,首单词应该小写,后续单词的首字母大写。

  • uerName、studentName (驼峰式命名法)

  • 给内存空间赋值,该值就是变量值。

数据类型

  • 基本数据类型

byte、int、short、long、float、double、char、boolean

数值类型(整数、小数)占用字节
byte1 个字节 (8位)
int4 个字节(32位)
short2 个字节(16位)
long8 个字节(64位)
float4 个字节(32位) 单精度浮点型
double8 个字节(64位)双精度浮点型
非数值类型占用字节
char字符 2 个字节(16位)
boolean1/8 个字节
  • 引用数据类型

数据类型转换

  • 自动转换

Java 可以自动对某些数据类型进行自动转换。

规则:只能由低字节向高字节进行转换,反之则不行。

byte->short->int->long->float->double

  • 强制类型转换

Java 无法自动转换的数据类型,开发者可以通过强制手段进行转换。

一般来讲强制类型转换可能会造成精度损失。

double num = 10.0;
int num2 = (int)num;

运算符

赋值运算符

数据类型 变量名 = 数值/变量;

//1、创建变量用来记录张三的体重
double weight1 = 70.5;
//2、创建变量表示李四的体重
double weight2 = 60.5;
System.out.println("交换之前:张三的体重是"+weight1+",李四的体重是"+weight2);
System.out.println("进行交换");
double temp = weight1;
weight1 = weight2;
weight2 = temp;
System.out.println("交换之后:张三的体重是"+weight1+",李四的体重是"+weight2);

算术运算符

  • 基本算术运算符

    +、-、*、/、%、++、–

    变量1 + 变量2

    变量1 - 变量2

    变量1 * 变量2

    变量1 / 变量2

    变量1 % 变量2

    变量++、++变量

    变量–、--变量

    变量++:先操作,再运算。

    ++变量:先运算,再操作。

    复合算术运算符

    +=、-=、*=、/=、%=

    变量1 += 变量2:先求出变量1和变量2之和,再把计算结果赋值给变量1,变量1 = 变量1 + 变量2

关系运算符

==、!=、>、<、>=、<=

逻辑运算符

逻辑运算符只能用于 boolean 类型的数据运算,判断 boolean 数据之间的逻辑关系,与、或、非。

&(与)、|(或)、!(非)、&&(短路与)、||(短路或)

参与逻辑运算符的变量都是 boolean 的

变量1 & 变量2:只有当变量 1 和变量 2 都为 true,结果为 true,否则为 false。

变量1 | 变量2:变量 1 和变量 2 只要有一个为 true,结果为 true,否则为 false。

!变量1:若变量 1 为 true,结果为 false,若变量 1 为 false,结果为 true。

变量1 && 变量2:只有当变量 1 和变量 2 都为 true,结果为 true,否则为 false。

变量1 || 变量2:变量 1 和变量 2 只要有一个为 true,结果为 true,否则为 false。

int num1 = 10;
int num2 = 11;
System.out.println((++num1==num2)||(num1++==num2));
System.out.println(num1);

int num1 = 10;
int num2 = 11;
System.out.println((++num1==num2)|(num1++==num2));
System.out.println(num1);

int num1 = 10;
int num2 = 11;
System.out.println((num1++==num2)&(++num1==num2));
System.out.println(num1);

int num1 = 10;
int num2 = 11;
System.out.println((num1++==num2)&&(++num1==num2));
System.out.println(num1);

条件运算符

三元运算符、三目运算符、三元表达式

根据不同的条件给同一个变量赋不同的值,变量 = 条件?值1:值2.

位运算符

  • 十进制和二进制的转换

十进制转二进制:目标数除以2,若能除尽,该位记做0,若除不尽,该位记做1,再对商继续除以2,以此类推,直到商为0,然后把每一位的结果反序组合就是对应的二进制。

10:1010

17:10001

二进制转十进制:从目标数的最后侧起,本位的数值乘以本位的权重,权重就是2的第几位的位数减一次方,将每一位的值进行相加,得到的结果就是对应的十进制。

位运算符:&(按位与)、|(按位或)、^(按位异或)、<<(左移)、>>(右移)

变量1 & 变量2:先把变量 1 和变量 2 转为二进制,每一位的数字一一对应,进行比较判断,若都为 1,则该位记做 1,否则记做 0。

变量1 | 变量2:先把变量 1 和变量 2 转为二进制,每一位的数字一一对应,进行比较判断,只要有一个为 1,则该位记做 1,否则记做 0。

变量1 ^ 变量2:先把变量 1 和变量 2 转为二进制,每一位的数字一一对应,进行比较判断,相同记做 0,不同记做 1。

变量1 << 变量2:变量1乘以2的变量2次方

2 << 3 : 2 * 8 = 16

变量1 >> 变量2:变量1除以2的变量2次方

2 >> 3:2/8 = 0

运算符的优先级

!>算术运算符>关系运算符>逻辑运算符(&&>||)

流程控制

判断

  • if else

用来判断某个条件是否成立,然后执行不同的逻辑运算。

基本语法:

if(判断条件){
  //条件成立的代码
}else{
  //条件不成立的代码
}
  • 多重 if

173 M

173~178 L

178 XL

  • if 后面必须跟条件

  • else 后面不能跟条件

  • else 后面可以根据{},也可以跟 if

  • switch-case

与 if 不同的是,switch-case 只能完成等值判断,而无法完成判断大小。

如果是判断两个值是否相等,可以使用 switch-case,如果比较两个值的大小关系,则不能使用 switch-case。

switch 支持 int、short、byte、char、枚举、String 类型,不支持 boolean 类型。

基本语法

switch(变量){
	case1:
		//业务代码
	breakcase2:
		//业务代码
	breka;
	...
	default:
		//业务代码
	break;
}

case 判断变量是否等于某个值,default 表示所有的 case 都不成立的情况下所执行的代码。

  • 1 奖励 2000
  • 2 奖励 1000
  • 3 奖励 500
  • 否则没有奖励
public static void main(String[] args) {
  int placing = 1;
  if(placing == 1) {
    System.out.println("奖励2000元");
  }else {
    if(placing == 2) {
      System.out.println("奖励1000元");
    }else {
      if(placing == 3) {
        System.out.println("奖励500元");
      }else{
        System.out.println("没有奖励");
      }
    }
  }

  switch(placing) {
    case 1:
      System.out.println("奖励2000元");
      break;
    case 2:
      System.out.println("奖励1000元");
      break;
    case 3:
      System.out.println("奖励500元");
      break;
    default:
      System.out.println("没有奖励");
      break;
  }
}

循环

for、while、do-while、foreach

循环四要素:

  • 初始化循环变量
  • 循环条件
  • 循环体
  • 更新循环变量
while
初始化循环变量
while(循环条件){
	循环体
	更新循环变量
}
//初始化循环变量
int num = 0;
//循环条件
while(num < 10) {
  //循环体
  System.out.println("Hello World");
  //更新循环变量
  num++;
}
int num = 0;
String flag = "y";
while(flag.equals("y")) {
  System.out.print("请输入学生学号:");
  Scanner scanner = new Scanner(System.in);
  int id = scanner.nextInt();
  switch(id) {
    case 1:
      System.out.println("张三的成绩是96");
      break;
    case 2:
      System.out.println("李四的成绩是91");
      break;
    case 3:
      System.out.println("王五的成绩是89");
      break;
    default:
      System.out.println("请输入正确的学号");
      break;
  }
  System.out.print("是否继续?y/n");
  flag = scanner.next();
}
System.out.println("感谢使用学生成绩查询系统");
do-while
//初始化循环变量
int num = 0;
do {
  //循环体
  System.out.println("Hello World");
  //更新循环变量
  num++;
}while(num<10);
//循环条件
Scanner scanner = new Scanner(System.in);
String result = "";
do {
  System.out.println("张三参加体能测试,跑1000米");
  System.out.print("是否合格?y/n");
  result = scanner.next();
}while(result.equals("n"));
System.out.println("合格,通过测试");
for
for(初始化循环变量;循环条件;更新循环变量){
		循环体
}
for(int num = 0;num < 10;num++) {
  System.out.println("Hello World");
}
while、do-while、for 3种循环的区别
  • 相同点:都遵循循环四要素,初始化循环变量、循环条件、循环体、更新循环变量。
  • 不同点:
    • while 和 do-while 适用于循环次数不确定的业务场景;for 适用于循环次数确定的场景。
    • while 和 for 都是先判断循环条件,再执行循环体;do-while 先执行循环体,再判断循环条件。

分别使用 while、do-while、for 循环输出 10 以内的所有奇数。

//while循环
int num = 0;
while(num <= 10) {
  if(num%2!=0) {
    System.out.println(num);
  }
  num++;
}
//do-while循环
int num = 0;
do {
  if(num%2!=0) {
    System.out.println(num);
  }
  num++;
}while(num <= 10);
//for循环
for(int num = 0;num <= 10;num++) {
  if(num%2!=0) {
    System.out.println(num);
  }
}

for 循环只适用于循环次数确定的场景下(for 也可以适用于循环次数不确定的场景,只不过一般不会用这种方式进行开发),while 和 do-while 循环次数确定或者不确定都可以使用。

String result = "n";
for(;result.equals("n");) {
  System.out.println("张三参加体能测试,跑1000米");
  System.out.print("是否合格?y/n");
  result = scanner.next();
}
System.out.println("合格,通过测试");

数组

数组就是一种可以存储大量数据类型相同的变量的数据结构,数组就是一个具有相同数据类型的数据集合。

数组中的数据必须是同一种数据类型的。

基本要素

  • 数组名称
  • 数组元素
  • 元素下标
  • 数据类型

数组本身就是一个变量,数组名称就是变量名,数组中保存的每一个数据都会有一个下标(从 0 开始)

//声明数组
int[] array;
//分配内存空间
array = new int[6];
//给数组赋值
array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
array[4] = 5;
array[5] = 6;

int[] array2 = {1,2,3,4,5,6};
int[] array3 = new int[]{1,2,3,4,5,6};

常见错误

  • 数据类型不匹配。
  • 边声明边赋值的方式,代码必须写在同一行,不能换行。
  • 数组下标越界。

常用操作及方法

  • 求数组的最大值
  • 求数组的最小值
  • 在数组的指定位置插入数据
  • 对数组进行排序

二维数组

二维数组简单理解即一维数组中保存的值是另外一个一维数组。

变量、数据类型、流程控制、循环、数组。

综合练习1

用户管理系统

  • 查询用户:将系统中保存的全部用户信息在控制台打印输出。
  • 添加用户:向系统中添加新的用户信息,如果添加的用户已经存在,给出提示信息。
  • 删除用户:输入用户名,进行删除操作,若输入的用户名不存在,给出提示信息。
  • 账号冻结:输入用户名,进行冻结操作,若输入的用户名不存在或者该用户已经被冻结,给出相应提示。
  • 账号解冻:输入用户名,进行解封操作,若输入的用户名不存在或者该用户状态正常,给出相应提示。
  • 退出系统:跳出循环,给出提示信息。
import java.util.Arrays;
import java.util.Scanner;

public class Comprehensive_Practice {
	static String[] names = {"张三","李四","王五","小明"};
	static int[] ages = {22,23,20,25};
	static String [] states = {"正常","正常","正常","正常"};
	public static void main(String[] args) {
		//初始化用户数据(用户名、年龄、状态)
		//Object[] data={"张三",22,"正常"};

		Scanner scanner= new Scanner(System.in);
		int num;
		
	 do{
		System.out.println("------欢迎使用用户管理系统------");
		System.out.println("1.查询用户");
		System.out.println("2.添加用户");
		System.out.println("3.删除用户");
		System.out.println("4.账号冻结");
		System.out.println("5.账号解封");
		System.out.println("6.退出系统");
		System.out.println("请选择:");
		
		 num=scanner.nextInt();
		
	switch(num) {
	case 1:
		System.out.println("------查询用户------");
		System.out.println("编号\t\t姓名\t\t年龄\t\t状态");
		for(int i=0;i<names.length;i++) {
			if(names[i]!=null)
			System.out.println((i+1)+"\t\t"+names[i]+"\t\t"+ages[i]+"\t\t"+states[i]);
		}
		System.out.println("输入0返回上一菜单");
		num=scanner.nextInt();
		break;	
	case 2:
		System.out.println("------添加用户------");
		System.out.println("请输入用户的姓名:");
		String name = scanner.next();
		if(nameIsExist(name)) {
			System.out.println(name+"名字已存在,请勿重复添加!");}
		
			else {if(names[names.length-1]!=null) {
				//创建新的数组,并且将老数组的值存入新数组
				names = Arrays.copyOf(names,names.length+1);
				names[names.length-1]=name;
				System.out.println("请输入"+name+"的年龄");
				int age = scanner.nextInt();
				ages=Arrays.copyOf(ages, ages.length+1);
				ages[ages.length-1]=age;
				states = Arrays.copyOf(states,states.length+1);
				states[states.length-1]="正常";
			}else {
				int index=getFirstNull();
				names[index]=name;
				System.out.println("请输入"+name+"的年龄");
				int age = scanner.nextInt()	;
				ages[index]=age;
				states[index]="正常";
				
				
			}
			
		}
		
//		if(names[names.length-1]!=null) {
//			System.out.println("数组已经填满,新用户无法加入");
//		}
//		else {
//			System.out.println("请输入用户姓名:");
//			String name = scanner.next();
//			boolean flag = nameIsExist(name);
//			if(flag) {
//				System.out.println(name+"已存在,请勿重复添加!");}
//				else {
//					names[names.length-1] = name;
//					System.out.println("请输入"+name+"的年龄");
//					int age = scanner.nextInt();
//					states[states.length-1]="正常";
//							System.out.println("添加成功");
//				}
//			}
		System.out.println("输入0返回上一菜单");
		num=scanner.nextInt();			
		break;	
	case 3:
		System.out.println("-----删除用户------");
		if(names[0]==null) {
			System.out.println("用户已经全部删除!");
		}
		else {
			System.out.println("请输入用户名");
			name = scanner.next();
			if(nameIsExist(name)){
				int index = getIndex(name);
				if(index>=0) {
					for(int i = index;i<names.length-1;i++) {
						names[i] = names[i+1];
						ages[i] = ages[i+1];
						states[i] = states[i+1];
					}
					names[names.length-1]=null;
					ages[ages.length-1]=0;
					states[states.length-1]=null;
					}
				}
				
				
			else {
				System.out.println("您输入的用户不存在!");
			}
			
		}	
	System.out.println("输入0返回上一菜单");
	num=scanner.nextInt();	
		break;	
	case 4:
		System.out.println("------账号冻结------");
		System.out.println("请输入用户名:");
		name = scanner.next();
		if(nameIsExist(name)) {
		    int index = getIndex(name);
		    String state = states[index];
		    if(state.equals("冻结")) {
		    	System.out.println(name+"账号已经被冻结,请勿重复操作");
		    }else {
		    	states[index]="冻结";
		    	System.out.println(name+"冻结成功");
		    }
		    
		}else {
			System.out.println("您输入的用户不存在!");
			}
		System.out.println("输入0返回上一菜单");
		num=scanner.nextInt();	
		break;	
	case 5:
		System.out.println("------账号解封------");
		System.out.println("请输入用户名");
	    name = scanner.next();
		if(nameIsExist(name)) {
			int index=getIndex(name);
			String state= states[index];
			if(state.equals("正常")) {
				System.out.println(name+"已解封,请勿重复操作");
			}else {
				states[index]="正常";
				System.out.println("成功解封");
			}
		}else {
			System.out.println("您输入"+name+"账号不存在");
		}
		System.out.println("输入0返回上一菜单");
		num=scanner.nextInt();	
		break;	
	case 6:
		System.out.println("感谢使用本系统,再见!");
		break;	
		default:
	    break;
	}
	 }while(num==0);
			
	
	}
         /**
          * 判断用户输入的姓名是否已经存在于数组中
          */
      public static boolean nameIsExist(String name) {
    	  for(int i=0;i<names.length;i++) {
    		  if(name.equals(names[i])) {
    			  return true;
    		  }
    	  }
    	  return false;
      }
      /**
       * 找到名字在数组中的下标
       */
      public static int getIndex(String name) {
    	  for(int i = 0;i <names.length;i++ ) {
    		  if(name.equals(names[i])) {
    		  return i ;
    		  }
    	  }
    	  return -1;
      }
      /**
       * 找到数组中第一个为空的下标
       */
      public static int getFirstNull() {
    	  for(int i=0;i<names.length;i++) {
    	  if(names[i] == null) {
    		  return i ;
    	  }
    	 
    	  }
		return -1;
      }
}




面向对象

三大特征:封装、继承、多态

面向对象编程思想:将程序模块化的思想。

  • 什么是面向对象?

面向对象编程思想诞生之前,程序开发采用的是面向过程的结构化编程方式,是一种面向功能划分的软件结构。

最小粒度细化到方法这一层。

面向过程注重的是每一个步骤,面向对象关注点在于整件事情的模块化结构。

  • 类和对象

类和对象的关系

每个对象都有特定的特征:

  1. 属性
  2. 方法

属性指的是对象的静态特征,方法用来描述对象的动态特征。

对象是用来描述客观存在的一个实体,改实体是由一组属性和方法构成。

类是与对象紧密结合的另外一个概念,类是产生对象的模版,所有的对象都是通过类来创建的。

二者的关系:类是对象的抽象化描述,这些对象具有相同的特征和动作(属性和方法)。

对象是类的具体实例。

Java 程序是以类位组织单元,程序运行时的主体是通过类创建的具体对象。

定义类

public class 类名{
	//定义属性,属性名符合驼峰式命名法
	public 数据类型 属性名;
	//定义方法,方法名符合驼峰式命名法
	public 返回值类型 方法名(参数列表:数据类型 参数名){
		//方法体
	}
}

Java 关于返回值的定义分为两类:有返回值和无返回值,有返回值的方法需要在方法定义时指定返回值的数据类型,并在方法体中用 return 将结果返回给外部调用者,加法运算。

如果一个方法不需要进行返回操作,将返回值类型定义为 void。

参数列表是指外部在调用该方法时需要传入到方法内部进行运算的数据。

构造函数、构造方法、构造器

构造函数是一种特殊的方法,普通方法是用来描述某个动作的,构造方法是用来创建对象的。

  • 方法名必须与类名一致。
  • 不需要定义返回值类型。

构造函数可分为有参构造和无参构造,有参构造是指带参数的构造函数,无参构造是指没有参数的构造函数。

任何一个类都默认自带一个无参构造函数,如果手动在类中定义一个有参构造,则会覆盖默认的无参构造。

this 关键字

this 用来指代当前类的实例化对象,通过 this 可以调用当前类的属性和方法,比如在有参构造中,通过 this 将外部传入的值赋给当前类的实例化对象。

this 除了可以在类中访问属性也可以在类中调用方法,类中的方法可以分为两类:构造方法、普通方法。

用 this 调用这两类方法的语法也不同,调用构造函数的语法是 this(参数列表),不能在普通方法中使用 this 调用构造函数。

用 this 调用普通方法,this.方法名(参数列表),可以在构造函数中使用,也可以在普通方法中使用。

成员变量和局部变量

变量的作用域是指在程序中可以通过变量名来访问该变量的范围,变量的作用域由变量被声明时所在位置决定的,Java 中根据不同的作用域可以将变量分为成员变量和局部变量。

局部变量:如果一个变量在方法中声明,则该变量是局部变量。

成员变量:如果一个变量在方法外,类中声明,则该变量是成员变量。

public class HelloWorld{
	int num2 = 2;
	public int test(){
		int num1 = 1;
	}
}

1、成员变量和局部变量的区别在于作用域不同,成员变量的作用域在整个类中,类中的每个方法都可以访问该变量,局部变量的作用域只在定义该变量的方法中,出了方法体就无法访问。

2、成员变量和局部变量的初始值也不同,局部变量不会赋初始值,成员变量会赋初始值,具体的值是由成员变量的数据类型决定的。

封装

封装是指将类的属性隐藏在内部,外部不能直接访问和修改,如何实现?通过修改成员变量的可见性,从公有改为私有。

public class Student {
	private int id;
	private String name;
	private int age;
	public void show() {
		System.out.println("学生信息如下:");
		System.out.println("学生编号:"+id);
		System.out.println("学生姓名:"+name);
		System.out.println("学生年龄:"+age);
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		if(age <= 0) {
			System.out.println("输入的数值有误!");
			age = 18;
		}
		this.age = age;
	}
}

封装的核心思想就是尽可能把属性都隐藏在内部,对外提供方法来访问,我们可以在这些方法中添加逻辑处理来实现过滤,以屏蔽错误数据的赋值。

封装的步骤:

  • 修改属性(成员变量)的访问权限为私有,使得外部不能直接访问。
  • 提供外部可以直接调用的方法。
  • 在该方法中加入对于属性的逻辑控制,避免出现逻辑上的错误。

什么是访问权限?

访问权限是指该属性可以被直接访问的范围,是在属性定义时设定的,访问权限的可选项一共有 4 种:public、private、默认(不写)、protected,区别在于作用域范围不同。

static关键字

static 表示静态或者全局,可以用来修饰成员变量和成员方法以及代码块。

使用 static 修饰的成员变量和成员方法独立于该类的任何一个实例化对象,访问时不依赖于该类的对象,而是直接通过类去访问,可以理解为被该类的所有实例对象所共用,所以说是全局的。

static 还可以修饰代码块,被 static 修饰的代码块叫做静态代码块。

static {
  System.out.println(1);
}

静态代码块的特点是只执行一次,什么时候执行?当这个类被加载到内存时执行,不需要开发者手动调用,会自动执行。

被加载到内存中的类叫做运行时类,静态代码块就是在家中类的时候执行的,因为类只加载一次,所以静态代码块也只执行一次。

继承

  • 什么是继承?

继承是用来描述类之间的关系的,即一个类继承(拥有)另外一个类中的属性和方法,被继承的类叫做父类,继承父类的类叫做子类。

继承的基本语法:

public class 类名 extends 父类名{

}
public class People {
	private int id;
	private String name;
	private int age;
	private char gender;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public char getGender() {
		return gender;
	}
	public void setGender(char gender) {
		this.gender = gender;
	}
}
public class Student extends People {
	
}

Java 中的继承是单继承,也就是说一个子类只能有一个直接父类。

子类访问父类

创建一个子类对象的时候,会默认先创建一个父类对象,无论是通过有参构造或是无参构造来创建子类对象,都是通过无参构造来创建父类对象的。

可以通过 super 关键字让子类创建对象时调用父类的有参构造。

public Student() {
  super(1);
  System.out.println("通过无参构造创建了Student对象");
}

子类可以访问父类的构造方法、普通方法、成员变量,都是通过 super 关键字来完成,具体语法:

构造方法:super(参数列表)
普通方法:super.方法名(参数列表)
成员变量:super.成员变量名

在子类的构造方法中,可以通过 super 访问父类的构造方法和普通方法。

在子类的普通方法中,只能通过 super 访问父类的普通方法。

子类的访问权限

访问权限修饰符:public、protected、默认修饰符、private。

修饰符同一个类中不同包同包子类(不同包)
public可以可以可以可以
protected可以不可可以可以
默认修饰符可以不可可以不可
private可以不可不可不可

包:package,用来管理 Java 文件,一个项目中不可避免会出现同名的 Java 类,为了防止产生冲突,可以把同名的 Java 类分别放入不同的包中。

包的命名规范:包名由小写字母组成,不能以 . 开头或结尾,可以包含数字,但不能以数字开头,使用 . 来分层。

包的命名方式一般采用网络域名的反向输出,如 com.company.test/com.company.entity。

方法重写

子类在继承父类方法的基础上,对父类方法重新定义并覆盖的操作叫做方法重写。

构造方法不能被重新,方法重写的规则:

1、父子类的方法名相同。

2、父子类的方法参数列表相同。

3、子类方法的返回值与父类方法返回值类型相同或者是其子类。

4、子类方法的访问权限不能小于父类。

方法重写 VS 方法重载

位置:方法重写在子类中对父类方法进行重写,方法重载是在同一个类中。

方法名:方法重写相同,方法重载相同。

参数列表:方法重写相同,方法重载不同。

返回值:方法重写相同或是其子类,方法重载没有要求。

访问权限:方法重写不能小于父类,方法重载没有要求。

多态

一个事物具有多种表现形态,在 Java 程序中,定义一个方法,在具体的生成环境中根据不同的需求呈现不同的业务逻辑,多态的前提是继承。

package com.oakine.test;

public class Memeber {
	public void buyBook() {
		
	}
}
package com.oakine.test;

public class OrdinaryMember extends Memeber {
	public void buyBook() {
		System.out.println("普通会员买书打9折");
	}
}
package com.oakine.test;

public class SuperMember extends Memeber {
	public void buyBook() {
		System.out.println("超级会员买书打6折");
	}
}
package com.oakine.test;

public class Cashier {
	private Memeber memeber;
	
	public Memeber getMemeber() {
		return memeber;
	}

	public void setMemeber(Memeber memeber) {
		this.memeber = memeber;
	}

	public void settlement() {
		this.memeber.buyBook();
	}
}
package com.oakine.test;

public class Test {
	public static void main(String[] args) {
		OrdinaryMember ordinaryMember = new OrdinaryMember();
		SuperMember superMember = new SuperMember();
		Cashier cashier = new Cashier();
		cashier.setMemeber(superMember);
		cashier.settlement();
	}
}

多态的具体使用有两种形式:

1、定义方法时形参类型为父类,实际调用方法时传入子类类型的参数。

2、定义方法时返回值类型为父类,实际调用方法时返回子类对象。

以上两种形式的基本原理都是父类引用可以指向子类对象。

public void settlement(Memeber memeber) {
  memeber.buyBook();
}

Cashier cashier = new Cashier();
OrdinaryMember ordinaryMember = new OrdinaryMember();
cashier.settlement(ordinaryMember);
public Member getMember(String name) {
  if(name.equals("ordinary")) {
    return new OrdinaryMember();
  }else {
    return new SuperMember();
  }
}

抽象方法和抽象类

如果一个方法只有方法的声明而没有具体的方法实现,这个方法就叫做抽象方法,Java 中的抽象方法需要使用 abstract 关键字来修饰。

public abstract void buyBook();

一旦类中定义了抽象方法,则该类也必须声明为抽象类,需要在类定义处添加 abstract 关键字。

public abstract class Member {
	public abstract void buyBook();
}

抽象类与普通类的区别是抽象类不能被实例化,抽象方法与普通方法的区别是抽象方法没有方法体。

抽象类中可以没有抽象方法,但是包含了抽象方法的类必须定义为抽象类。即我们可以在抽象类中定义普通方法,但是在普通类中不能定义抽象方法。

如果父类是抽象类,一旦子类继承了该抽象父类,则子类必须对父类的抽象方法进行重写,否则程序报错。

package com.oakine.test;

public abstract class Member {
	public abstract void buyBook();
}
package com.oakine.test;

public class SuperMember extends Member {
	@Override
	public void buyBook() {
		// TODO Auto-generated method stub
		System.out.println("超级会员买书打6折");
	}
}

如果子类也是抽象类,则可以不用重写父类的抽象方法。

Object

Object 是 Java 官方提供的类,存放在 java.lang 包中,该类是所有类的直接父类或者间接父类,无论是 Java 提供的类还是开发者自定义的类,都是 Object 的直接子类或间接子类,Java 中的任何一个类都会继承 Object 中的 public 和 protected 方法。

hashCode();
getClass();
equals(null);
clone();
toString();
notify();
notifyAll();
wait();
wait(1000L);
wait(1000L, 100);

Object 类中经常被子类重写的方法:

1、public String toString() 以字符串的形式返回对象的信息

2、public boolean equals(Object obj) 判断两个对象是否相等

3、public native int hashCode() 返回对象的散列码

  • toString

Object

public String toString() {
  return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

重写之后

@Override
public String toString() {
  return "People [id=" + id + ", name=" + name + ", score=" + score + "]";
}
  • equals

Object

public boolean equals(Object obj) {
  return (this == obj);
}

重写之后

@Override
public boolean equals(Object obj) {
  // TODO Auto-generated method stub
  People people = (People)obj;
  if(this.id == people.id && this.name.equals(people.name) && this.score.equals(people.score)) {
    return true;
  }
  return false;
}
  • hashCode

Object

public native int hashCode();

重写之后

@Override
public int hashCode() {
  // TODO Auto-generated method stub
  return (int) (id*name.hashCode()*score);
}

包装类

  • 什么是包装类?

包装类是 Java 提供的一组类,专门用来创建 8 种基本数据类型对应的对象,一共有 8 个包装类,存放在 java.lang 包中,基本数据类型对应的包装类。

byte Byte

short Short

int Integer

long Long

float Float

double Double

char Character

boolean Boolean

体系结构

在这里插入图片描述

装箱和拆箱

装箱和拆箱是包装类的特有名词,装箱是指将基本数据类型转为对应的包装类对象,拆箱就是将包装类对象转为对应的基本数据类型。

装箱

public Type(type value)

每个包装类都提供了一个有参构造函数:public Type(type value),用来实例化包装类对象。

byte b = 1;
Byte byt = new Byte(b);
short s = 2;
Short shor = new Short(s);
int i = 3;
Integer integer = new Integer(i);
long l = 4;
Long lon = new Long(l);
float f = 5.5f;
Float flo = new Float(f);
double d = 6.6;
Double dou = new Double(d);
char cha = 'J';
Character charac = new Character(cha);
boolean bo = true;
Boolean bool = new Boolean(bo);
System.out.println(byt);
System.out.println(shor);
System.out.println(integer);
System.out.println(lon);
System.out.println(flo);
System.out.println(dou);
System.out.println(charac);
System.out.println(bool);

2、public Type(String value)/public Type(char value)

每个包装类还有一个重载构造函数,Character 类的重载构造函数:public Type(char value),其他包装类的重载构造函数:public Type(String value)。

Byte byt = new Byte("1");
Short shor = new Short("2");
Integer integer = new Integer("3");
Long lon = new Long("4");
Float flo = new Float("5.5f");
Double dou = new Double("6.6");
Character charac = new Character('J');
Boolean bool = new Boolean("abc");
System.out.println(byt);
System.out.println(shor);
System.out.println(integer);
System.out.println(lon);
System.out.println(flo);
System.out.println(dou);
System.out.println(charac);

3、valueOf(type value) 静态方法,参数是基本数据类型的数据

每一个包装类都有一个 valueOf(type value) 方法

byte b = 1;
Byte byt = Byte.valueOf(b);
short s = 2;
Short shot = Short.valueOf(s);
int i = 3;
Integer integer = Integer.valueOf(i);
long l = 4L;
Long lon = Long.valueOf(l);
float f = 5.5f;
Float floa = Float.valueOf(f);
double d = 6.6;
Double doub = Double.valueOf(d);
boolean boo = true;
Boolean bool = Boolean.valueOf(boo);
char ch = 'J';
Character cha = Character.valueOf(ch);

4、valueOf(String value)/valueOf(char value) 专门为 Character 转换使用的,其他的 7 个包装类都可以使用 valueOf(String value)。

Byte byt = Byte.valueOf("1");
Short sho = Short.valueOf("2");
Integer integer = Integer.valueOf("3");
Long lon = Long.valueOf("4");
Float flo = Float.valueOf("5.5f");
Double dou = Double.valueOf("6.6");
Boolean boo = Boolean.valueOf("true");
Character cha = Character.valueOf('J');

需要注意的是,Boolean 类的构造函数中,当参数为 “true” 时,Boolean 值为 true,当参数不为 “true”,Boolean 值为 false。

拆箱

1、*Value()

每个包装类都有一个 *Value() 方法,通过该方法可以将包装类转为基本数据类型。

Byte byt = Byte.valueOf("1");
Short sho = Short.valueOf("2");
Integer integer = Integer.valueOf("3");
Long lon = Long.valueOf("4");
Float flo = Float.valueOf("5.5f");
Double dou = Double.valueOf("6.6");
Boolean boo = Boolean.valueOf("true");
Character cha = Character.valueOf('J');

byte b = byt.byteValue();
short sh = sho.shortValue();
int i = integer.intValue();
long l = lon.longValue();
float f = flo.floatValue();
double d = dou.doubleValue();
boolean bo = boo.booleanValue();
char c = cha.charValue();

2、parse*(String value)

除了 Character 类以外的每一个包装类都有一个静态方法可以将字符串类型转为基本数据类型。

byte b = Byte.parseByte("1");
short s = Short.parseShort("2");
int i = Integer.parseInt("3");
long l = Long.parseLong("4");
float f = Float.parseFloat("5.5");
double d = Double.parseDouble("6.6");
boolean bo = Boolean.parseBoolean("true");

3、toString(type value)

每个包装类都有该方法,作用是将基本数据类型转为 String 类型。

byte b = 1;
String bstr = Byte.toString(b);
short s = 2;
String sstr = Short.toString(s);
String i = Integer.toString(3);
long l = 4L;
String lstr = Long.toString(l);
float f = 5.5f;
String fstr = Float.toString(f);
double d = 6.6;
String dstr = Double.toString(d);
boolean bo = true;
String bostr = Boolean.toString(bo);
String chstr = Character.toString('J');

接口

  • 什么是接口?

接口是由抽象类衍生出来的一个概念,并由此产生了一种编程方式:面向接口编程。

面向接口编程就是将程序中的业务模块进行分离,以接口的形式去对接不同的业务模块。

面向接口编程的优点:当用户需求变更时,只需要切换不同的实现类,而不需要修改串联模块的接口,减少对系统的影响。

1、能够最大限度实现解耦合,降低程序的耦合性。

2、使程序易于扩展。

3、有利于程序的后期维护。

  • 如何使用接口

接口在 Java 中时独立存在的一种结构,和类相似,我们需要创建一个接口文件,Java 中用 class 关键字来标识类,用 interface 来标识接口,基本语法:

public interface 接口名{
	public 返回值 方法名(参数列表)
}

接口其实就是一个抽象类,极度抽象的抽象类。

抽象类:一个类中一旦存在没有具体实现的抽象方法时,那么该类就必须定义为抽象类,同时抽象类允许存在非抽象方法。

但是接口完全不同,接口中不能存在非抽象方法,接口中必须全部是抽象方法。

因为接口中必须全部都是抽象方法,所以修饰抽象方法的关键字 abstract 可以省略。

接口中允许定义成员变量,但是有如下要求:

1、不能定义 private 和 protected 修饰的成员变量,只能定义 public 和默认访问权限修饰符修饰的成员变量。

2、接口中的成员变量在定义时就必须完成初始化。

3、接口中的成员变量都是静态常量,即可以直接通过接口访问,同时值不能被修改。

package com.oakine.test;

public interface MyInterface {
	public int ID = 0;
	String NAME = "张三";
	public void test();
}

使用接口时,不能直接实例化接口对象,而必须实例化其实现类对象,实现类本身就是一个普通的 Java 类,创建实现类的代码如下所示。

package com.oakine.test;

public class MyInterfaceImpl implements MyInterface {

	@Override
	public void test() {
		// TODO Auto-generated method stub
		
	}

}

通过 implements 关键字来指定实现类具体要实现的接口,在实现类的内部需要对接口的所有抽象方法进行实现,同时要求访问权限修饰符、返回值类型、方法名和参数列表必须完全一致。

接口和继承,Java 只支持单继承,但是接口可以多实现(一个实现类可以同时实现多个接口)

package com.oakine.test;

public interface MyInterface {
	public int ID = 0;
	String NAME = "张三";
	public void fly();
}
package com.oakine.test;

public interface MyInterface2 {
	public void run();
}
package com.oakine.test;

public class MyInterfaceImpl implements MyInterface,MyInterface2 {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.out.println("实现了跑步的方法");
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("实现了飞行的方法");
	}

}
package com.oakine.test;

import java.util.ArrayList;
import java.util.List;

public class Test {
	public static void main(String[] args) {
		MyInterfaceImpl myInterfaceImpl = new MyInterfaceImpl();
		myInterfaceImpl.fly();
		myInterfaceImpl.run();
	}
}

面向接口编程的实际应用

面向接口编程是一种常用的编程方式,可以有效地提高代码的复用性,增强程序的扩展性和维护性。

  • 场景

某工厂生产产品 A,产品 A 主要是由设备 A 来完成生产,用程序模拟生产过程。

产品 B 是由设备 B 来生产的。

当需求发生改变时,就要频繁修改类的内部结构的方式是需要避免的,因为这种结构的程序扩展性很差,如何改进?使用面向接口编程即可。

1、创建接口 Equiment。

package com.oakine.test;

public interface Equiment {
	public void work();
}

2、创建 Equiment 的实现类。

package com.oakine.test;

public class EquipmentA implements Equiment {
	public void work() {
		System.out.println("设备A运行,生产产品A");
	}
}

package com.oakine.test;

public class EquipmentB implements Equiment {
	public void work() {
		System.out.println("设备B运行,生产产品B");
	}
}

package com.oakine.test;

public class EquipmentC implements Equiment {
	public void work() {
		// TODO Auto-generated method stub
		System.out.println("设备C运行,生产产品C");
	}
	
}

3、创建 Factory 类。

package com.oakine.test;

public class Factory {
	private Equiment equipment;

	public Equiment getEquipment() {
		return equipment;
	}

	public void setEquipment(Equiment equipment) {
		this.equipment = equipment;
	}
	
	public void work() {
		System.out.println("开始生产...");
		this.equipment.work();
	}
}

4、Test

package com.oakine.test;

public class Test {
	public static void main(String[] args) {
		//初始化工厂
		Factory factory = new Factory();
//		EquipmentB equipmentB = new EquipmentB();
//		factory.setEquipment(equipmentB);
//		EquipmentA equipmentA = new EquipmentA();
//		factory.setEquipment(equipmentA);
		EquipmentC equipmentC = new EquipmentC();
		factory.setEquipment(equipmentC);
		//开始工作
		factory.work();
	}
}

异常

什么是异常?

Java 中的错误大致可以分为两类:

一类是编译时错误,一般是指语法错误。

另一类是运行时错误。

Java 中有一组专门用来描述各种不同的运行时异常,叫做异常类,Java 结合异常类提供了处理错误的机制。

具体步骤是当程序出现错误时,会创建一个包含错误信息的异常类的实例化对象,并自动将该对象提交给系统,由系统转交给能够处理异常的代码进行处理。

异常可以分为两类:Error 和 Exception。

Error 是指系统错误,JVM 生成,我们编写的程序无法处理。

Exception 指程序运行期间出现的错误,我们编写的程序可以对其进行处理。

异常的使用

异常的使用需要用到两个关键字 try 和 catch,并且这两个关键字需要结合起来使用,用 try 来监听可能会抛出异常的代码,一旦捕获到异常,生成异常对象并交给 catch 来处理,基本语法如下所示。

try{
	//可能抛出异常的代码
}catch(Exception e){
	//处理异常
}
try{
	//可能会抛出异常的代码
}catch(Exception e){
	//对异常进行处理
}finally{
	//一定会执行的代码
}
package com.oakine.exception;

public class Test {
	public static void main(String[] args) {
		try {
			int num = 10/10;
		}catch (Exception e) {
			// TODO: handle exception
			if(e.getMessage().equals("/ by zero")) {
				System.err.println("分母不能为0");
			}
		}
	}
}

除了 try 和 catch,还可以使用 finally 关键字来处理异常,finally 的作用?

无论程序是否抛出异常,finally 代码块中的代码一定都会执行,finally 一般跟在 catch 代码块的后面,基本语法如下所示。

try{
	//可能抛出异常的代码
}catch(Exception e){
	//处理异常
}finally{
	//必须执行的代码
}

异常类

Java 将运行时出现的错误全部封装成类,并且不是一个类,而是一组类。同时这些类之间是有层级关系的,由树状结构一层层向下分级,处在最顶端的类是 Throwable,是所有异常类的根结点。

  • Error:系统错误,程序无法处理。
  • Exception:程序运行时出现的错误,程序可以处理。

Error 和 Exception 都是 Throwable 的子类,Throwable、Error、Exception 都是存放在 java.lang 包中。

Error 常见的子类:VirtualMachineError、AWTError、IOError。

VirtualMachineError 的子类:StackOverflowError、OutOfMemoryError,用来描述内存溢出等系统问题。

Exception 常见的子类:IOException 和 RuntimeException

IOException 存放在 java.io 包中,RuntimeException 存放在 java.lang 包中。

IOException 常见的子类:FileLockInterruptionException、FileNotFoundException、FilerException,这些异常通常都是处理通过 IO 流进行文件传输的时候发生的错误。

RuntimeException 常见的子类:

  • ArithmeticException:表示数学运算异常。
  • ClassNotFoundException:表类未定义异常。
  • IllelArgumentException:表示参数格式错误。
  • ArrayIndexOutOfBounds:表示数组下标越界。
  • NullPointException:表示空指针异常。
  • NoSuchMethodException:表示方法未定义异常。
  • NumberFormatException:表示将其他数据类型转为数值类型发生的类型不匹配异常。

throw 和 throws

throw 和 throws 是 Java 在处理异常时使用的两个关键字,都可以用来抛出异常,但是使用的方式和表示的含义完全不同。

Java 中抛出异常有 3 种方式:

  • try-catch
  • 使用 throw 是开发者主动抛出异常,即读到 throw 代码就一定抛出异常,基本语法:throw new Exception(),是一种基于代码的逻辑而主动抛出异常的方式。
public class Test {
	public static void main(String[] args) {
		int[] array = {1,2,3};
		test(array,2);
	}
	
	public static void test(int[] array,int index) {
		if(index >= 3 || index < 0) {
			try {
				throw new Exception();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else {
			System.out.println(array[index]);
		}
	}
}
  • try-catch 和 throw 都是作用于具体的逻辑代码,throws 是作用于方法的,用来描述方法可能会抛出的异常。

如果方法 throws 的是 RuntimeException 异常或者其子类,外部调用时可以不处理,JVM 会处理。

如果方法 throws 的是 Exception 异常或者其子类,外部调用时必须处理,否则报错。

public class Test {
	public static void main(String[] args) throws Exception {
		test("123");
	}
	
	public static void test(String str) throws Exception {
		int num = Integer.parseInt(str);
	}
	
}

异常捕获

  • 自动捕获 try-cath

  • throw 主动抛出异常

  • throws 修饰可能抛出异常的方法

自定义异常

除了使用 Java 提供的异常外,也可以根据需求来自定义异常。

package com.oakine.exception;

public class MyNumberException extends RuntimeException {
	public MyNumberException(String error) {
		super(error);
	}
}
package com.oakine.exception;

public class Test {
	public static void main(String[] args){
		Test test = new Test();
		System.out.println(test.add("a"));
	}
	
	public int add(Object object){
		if(object instanceof Integer) {
			int num = (int)object;
			return ++num;
		}else {
			String error = "传入的参数不是整数类型";
			MyNumberException myNumberException = new MyNumberException(error);
			throw myNumberException;
		}
	}
}

综合练习2

封装、继承、多态、抽象、接口、异常完成一个汽车查询系统。

需求描述:共有 3 种类型的汽车:小轿车、大巴车、卡车,其中小轿车的座位数是 4 座,大巴车座位数是 53 座,卡车座位数是 2 座,要求使用封装、继承、抽象来完成车辆的定义。

可以对车辆信息进行修改,卡车可以运货但是载重量不能超过 12 吨,使用自定义异常来处理错误,小轿车和大巴车没有此功能,要求使用接口来实现。

Car

package com.oakine.test;

public abstract class Car {
	private String name;
	private String color;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public Car(String name, String color) {
		super();
		this.name = name;
		this.color = color;
	}
	public abstract String seatNum();
}

Sedan

package com.oakine.test;

public class Sedan extends Car {

	public Sedan(String name, String color) {
		super(name, color);
	}

	@Override
	public String seatNum() {
		// TODO Auto-generated method stub
		return "4座";
	}
	
}

Bus

package com.oakine.test;

public class Bus extends Car {

	public Bus(String name, String color) {
		super(name, color);
		// TODO Auto-generated constructor stub
	}

	@Override
	public String seatNum() {
		// TODO Auto-generated method stub
		return "53座";
	}

}

Truck

package com.oakine.test;

public class Truck extends Car implements Container {
	
	private int weight;

	public Truck(String name, String color,int weight) {
		super(name, color);
		this.weight = weight;
		// TODO Auto-generated constructor stub
	}

	@Override
	public String seatNum() {
		// TODO Auto-generated method stub
		return "2座";
	}

	@Override
	public int getweight() {
		// TODO Auto-generated method stub
		return this.weight;
	}

}

Container

package com.oakine.test;

public interface Container {
	public int getweight();
}

CarException

package com.oakine.test;

public class CarException extends Exception {
	public CarException(String error) {
		super(error);
	}
}

Test

package com.oakine.test;

import java.util.Scanner;

public class Test {
	private static Scanner scanner;
	private static Sedan sedan;
	private static Bus bus;
	private static Truck truck;
	private static Car[] cars;
	static {
		scanner = new Scanner(System.in);
		sedan = new Sedan("小轿车","黑色");
		bus = new Bus("大巴车","绿色");
		truck = new Truck("卡车","蓝色",2);
		cars = new Car[3];
		cars[0] = sedan;
		cars[1] = bus;
		cars[2] = truck;
	}
	
	public void showCars() {
		System.out.println("欢迎使用本汽车管理系统");
		System.out.println("车辆名称\t\t车辆颜色\t\t座位数\t\t载重量");
		for(Car car:cars) {
			if(car instanceof Truck) {
				Truck truck = (Truck)car;
				System.out.println(car.getName()+"\t\t"+car.getColor()+"\t\t"+car.seatNum()+"\t\t"+truck.getweight());
			}else {
				System.out.println(car.getName()+"\t\t"+car.getColor()+"\t\t"+car.seatNum()+"\t\t不能拉货");
			}
		}
		System.out.println("1.小轿车\t2.大巴车\t3.卡车");
		System.out.print("请选择要修改的车辆:");
		int num = scanner.nextInt();
		switch(num) {
			case 1:
				update("sedan");
				break;
			case 2:
				update("bus");
				break;
			case 3:
				update("truck");
				break;
			default:
				System.out.println("车辆不存在!");
				break;
		}
	}
	
	public void update(String type) {
		String name = null;
		String color = null;
		if(type.equals("sedan")) {
			System.out.print("输入车辆名称");
			name = scanner.next();
			System.out.print("输入车辆颜色");
			color = scanner.next();
			Sedan sedan = new Sedan(name,color);
			cars[0] = sedan;
		}
		if(type.equals("bus")) {
			System.out.print("输入车辆名称");
			name = scanner.next();
			System.out.print("输入车辆颜色");
			color = scanner.next();
			Bus bus = new Bus(name,color);
			cars[1] = bus;
		}
		if(type.equals("truck")) {
			System.out.print("输入车辆名称");
			name = scanner.next();
			System.out.print("输入车辆颜色");
			color = scanner.next();
			System.out.print("输入载重量");
			int weight = scanner.nextInt();
			if(weight > 12) {
				CarException carException = new CarException("卡车的载重量不能超过12吨");
				try {
					throw carException;
				} catch (CarException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return;
				}
			}
			Truck truck = new Truck(name,color,weight);
			cars[2] = truck;
		}
		showCars();
	}
	
	public static void main(String[] args) {
		Test test = new Test();
		test.showCars();
	}
}

面向对象的高级部分,包括 Object 类、包装类、接口和异常。其中 Object 类是所有 Java 类的父类,定义了 Java 体系的基础资料,通过继承传递给 Java 的每一个类,通过方法重写和多态让整个 Java 体系具有很强的灵活性。

包装类是 Java 为基本数据类型提供封装的一组类,通过包装类我们可以将基本数据类型转为对象,这一点在面向对象编程中很重要。

接口是抽象类的扩展,是 Java 中实现多态的重要方式,可以降低程序的耦合性,让程序变得更加灵活多变。接口就相当于零件,我们可以自由地将这些零件进行组装、整合。

异常是 Java 中处理错误的一种机制,同样是基于面向对象的思想,将错误抽象成对象然后进行处理,这里需要关注的是对异常相关的几个关键字的使用,try、catch、finally、throw、throws。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值