Java零基础学习
-
删除Java的安装目录
-
删除环境变量中的JAVA_HOME
-
删除path下的关于Java的目录
-
使用cmd输入java -version参看是否删除成功
-
百度搜索下载JDK8
-
安装JDK8
-
配置环境变量
-
我的电脑->右键属性
-
环境变量->JAVA_HOME
-
配置path变量
-
-
打开cmd输入java -version测试安装是否成功
第一个Java程序-HelloWorld
-
新建一个hello.java文件
-
编写代码
public class Hello{
public static void main(String[] args){
System.out.println("hello,world!");
}
}
-
编译该java文件(javac hello.java),产生.class文件
-
运行class文件(java hello),输出 hello,world!
Java程序运行机制
-
编译型
将写好的.java文件编译成.class文件,当.java文件修改时.class不会立即修改,需要重新编译该.java文件.class文件才会修改
-
解释型
边写边解释运行,缺点是运行速度较慢
Java基础语法
注释
-
平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的,但是当项目结构一旦复杂起来,我们就需要用到注释了。
-
注释并不会被执行,是给我们写代码的人看的
-
书写代码是一个非常好的习惯
-
Java中的注释有三种:
-
单行注释(//注释内容)
-
多行注释(/*注释内容*/)
-
文档注释(/**+回车+注释内容)
-
标识符
-
关键字
关键字 | ||||
---|---|---|---|---|
abstract | assert | boolean | break | byte |
case | catch | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
-
Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符
-
标识符注意点
-
所有的标识符都应该以字母(A-Z或者a-z)、美元符($)、或者下划线(_)开始
-
首字符之后可以是字母(A-Z或者a-z)、美元符($)、下划线(_)或数字的任何字符组合
-
不能使用关键字作为变量名或方法名
-
标识符是大小写敏感的
-
可以使用中文命名,但是一般不建议这样去使用,也不建议使用拼音,很Low
-
变量
-
变量是什么: 就是可以变化的量
-
Java是一种强类型语言,每个变量都必须声明其类型
-
Java变量是一个程序中最基本的存储单元,其要素包括变量名,变量类型和作用域
type varName [=value] [{,varName[=value]}];
//数据类型 变量名 = 值; 可以使用逗号隔开来声明多个同类型变量
-
注意事项:
-
每个变量都有类型,类型可以是基本类型,也可以是引用类型
-
变量名必须是合法的标识符
-
变量声明是一条完整的语句,因此每一个声明都必须以分号结束
-
什么是字节
-
位(bit): 是计算机内部数据储存的最小单位,11001100是一个八位二进制数
-
字节(byte): 是计算机中数据处理的基本单位,习惯上用大写 B 来表示
-
1B(byte,字节) = 8bit(位)
-
字符: 是指计算机中使用的字母、数字、字和符号
进制
-
二进制: 0b10表示二进制的10
-
八进制: 010表示八进制的10
-
十进制: 10
-
十六进制: 0x10表示十六进制的10
变量作用域
-
类变量
-
实例变量
-
局部变量
public class Variable{
static int allClicks=0;// 类变量
String str="hello world";// 实例变量
public void method(){
int i=0;// 局部变量
}
}
常量
-
常量(Constant): 初始化(initialize)后不能再改变值!不会变动的值
-
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变
final 常量名 = 值;
final double PI = 3.14;
-
常量名一般使用大写字符
变量的命名规范
-
所有变量、方法、类名: 见名知意
-
类成员变量: 首字母小写和驼峰原则: monthSalary
-
局部变量: 首字母小写和驼峰原则
-
常量: 大写字母和下划线: MAX_VALUE
-
类名: 首字母大写和驼峰原则: Man,GoodMan
-
方法名: 首字母小写和驼峰原则: run(),runRun()
运算符
-
算术运算符: +, -, *, /, %, ++, --
-
赋值运算符: =
-
关系运算符: >, <, >=, <=, ==, != instanceof
-
逻辑运算符: &&, ||, !
-
位运算符: &, |, ^, ~, >>, <<, >>>(了解!!!)
-
条件运算符: ? : (三目运算符)
-
扩展赋值运算符: +=, -=, *=, /=
位运算符
public class BitOperation {
public static void main(String[] args) {
// 如何计算2^3最快
/*
* << 相当于*2
* >> 相当于/2
* */
System.out.println(2<<2);// 输出8
}
}
字符串连接符
public class StringConjunction {
public static void main(String[] args) {
int a=10;
int b=20;
System.out.println(a+b+"");// 输出30
System.out.println(""+a+b);// 输出1020
}
}
包机制
-
为了更好的组织类,Java提供了包机制,用于区别类名的命名空间。
-
包语句的语法格式为:
package pkg1[. pkg2[. pkg3...]];
-
一般利用公司域名倒置作为包名
-
为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用"import"语句可完成此功能
import package1[. package2...].(classname|*);
JavaDoc
-
javadoc命令是用来生成自己API文档的
-
参数信息
-
@author 作者名
-
@version 版本号
-
@since 指明需要最早使用的jdk版本
-
@param 参数名
-
@return 返回值情况
-
@throws 异常抛出情况
-
-
dos命令(需在该类所在地打开dos窗口): javadoc [-encoding utf-8 -charset utf-8] 类名.java
-
-
Java流程控制
Scanner对象
-
之前我们学的基本语法中我们并没有事先程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入。java.util.Scanner 是Java5的新特征,我们可以通过Scanner类来获取用户的输入。
-
基本语法:
Scanner scan=new Scanner(System.in);
-
通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前我们一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据
-
next():
-
一定要读取到有效字符后才可以结束输入
-
对输入有效字符之前遇到的空白,next()方法会自动将其去掉
-
只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
-
next()不能得到带有空格的字符串
-
-
nextLine():
-
以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符
-
可以获得空白
-
-
代码演示
public class Scanner {
public static void main(String[] args) {
// 创建一个扫描器对象,用于接收键盘数据
java.util.Scanner scanner=new java.util.Scanner(System.in);
System.out.println("使用next方式接收: ");
// 判断用户有没有输入字符串
/*if(scanner.hasNext()){
// 使用next方式接收
String str=scanner.next();// 输入hello world
System.out.println("输出的内容为: "+str);// 输出hello
}*/
if(scanner.hasNextLine()){
// 使用nextLine接收
String str=scanner.nextLine();// 输入hello world
System.out.println("输出的内容为: "+str);// 输出hello world
}
// 凡是IO流的类如果不关闭会一直占用资源,要养成好习惯用完就关掉
scanner.close();
}
}
顺序结构
-
Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行
-
顺序结构是最简单的算法结构
-
语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构
选择结构
-
if 单选泽结构
-
我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示
-
语法:
if(布尔表达式){
//如果布尔表达式为true将执行的语句
}
-
-
if 双选择结构
-
语法:
if(布尔表达式){
//如果布尔表达式的值为true执行
}{
//如果布尔表达式的值为false执行
}
-
-
if 多选择结构
-
语法:
if(布尔表达式1){
//如果布尔表达式1的值为true则执行代码
}
else if(布尔表达式2){
//如果布尔表达式2的值为true则执行代码
}
else if(布尔表达式3){
//如果布尔表达式3的值为true则执行代码
}
else{
//如果以上布尔表达式都不为true则执行代码
}
-
-
嵌套的if结构
-
使用嵌套的if ... else语句是合法的。也就是说你可以在另一个if或者else if语句中使用if或者else if语句。你可以像if 语句一样嵌套else if ... else
-
语法:
if(布尔表达式1){
// 如果布尔表达式1的值为true执行代码
if(布尔表达式2){
// 如果布尔表达式2的值为true执行代码
}
}
-
-
switch 多选择结构
-
多选择结构还有一个实现方式就是switch case语句
-
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
-
switch 语句中的变量类型可以是:
-
byte、short、int或者char
-
从Java SE 7 开始
-
switch支持字符串String类型了
-
同时case标签必须为字符串常量或字面量
-
switch(expression){
case value:
//语句
break;//可选
case value:
//语句
break;//可选
//你可以有任意数量的case语句
default://可选
//语句
} -
循环结构
-
while循环
-
while是最基本的循环,它的结构为:
while(布尔表达式){
//循环内容
} -
只要布尔表达式为true,循环就会一直执行下去
-
我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环
-
少部分情况需要循环一直执行,比如服务器的请求响应监听等
-
循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编辑中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃
public class While {
public static void main(String[] args) {
// 计算1+2+3+...+100=?
int i=1;
int sum=0;
while(i<=100){
sum+=i;
i++;
}
System.out.println(sum);
}
} -
-
do ... while 循环
-
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次
-
do ... while 循环和 while 循环相似,不同的是,do ... while 循环至少会执行一次
do{
//代码语句
}while(布尔表达式);-
while 和 do ... while 的区别:
-
while先判断后执行。do ... while 是先执行后判断
-
do ... while 总是保证循环体会被至少执行一次!只是他们的主要差别
-
-
-
for 循环
-
虽然所有循环结构都可以用while 或者 do...while表示,但Java提供了另一种语句——for循环,使一些循环结构变得更加简单
-
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构
-
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化; 布尔表达式; 更新){
//代码语句
}
-
-
增强for循环
-
Java5引入了一种主要用于数组或集合的增强型for循环
-
java增强for循环语法格式如下:
for(声明语句 : 表达式){
//代码语句
}-
声明语句: 声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等
-
表达式: 表达式是要访问的数组名,或者是返回值为数组的方法
-
-
break和continue
-
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
-
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
-
关于goto关键字
-
goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue
-
"标签"是指后面跟一个冒号的标识符,例如: label
-
对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是: 我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
public class Label {
public static void main(String[] args) {
//打印101-150之间所有的质数
//质数是指在大于1的自然数中,除了1和它本身以外不在有其他因数的自然数
//不建议使用
int count=0;
outer:
for (int i = 101; i < 150; i++) {
for(int j=2;j<i/2;j++){
if(i%j==0){
continue outer;
}
}
System.out.println(i+" ");
}
}
} -
-
练习: 打印一个三角形
public class Triangle {
public static void main(String[] args) {
// 打印三角形 5行
for(int i=1;i<=5;i++){
for(int j=5;j>=i;j--){
System.out.print(" ");
}
for(int j=1;j<=i;j++){
System.out.print("*");
}
for(int j=1;j<i;j++){
System.out.print("*");
}
System.out.println();
}
}
}
-
Java方法
何谓方法
-
System.out.println(),那么它是什么呢
-
Java方法是语句的集合,它们在一起执行一个功能
-
方法是解决一类问题的步骤的有序组合
-
方法包含与类或对象中
-
方法在程序中被创建,在其他地方被引用
-
-
设计方法的原则: 方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展
方法的定义
-
Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
-
方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
-
修饰符: 修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型
-
返回值类型: 方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void
-
方法名: 是方法的实际名称。方法名和参数表共同构成方法签名
-
参数类型: 参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
-
形式参数: 在方法被调用时用于接收外界输入的数据
-
实参: 调用方法时实际传给方法的数据
-
-
方法体: 方法体包含具体的语句,定义该方法的功能
-
-
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
方法调用
-
调用方法: 对象名.方法名(实参列表)
-
Java 支持两种调用方法的方式,根据方法是否返回值来选择
-
方法返回一个值的时候,方法调用通常被当做一个值。例如:
int larger=max(30, 40);
-
如果方法返回值是void,方法调用一定是一条语句。例如:
System.out.println("Hello world");
方法的重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法的重载的规则:
-
方法名称必须相同
-
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)
-
方法的返回类型可以相同也可以不相同
-
仅仅返回类型不同不足以成为方法到的重载
-
-
实现理论:
-
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
-
命令行传参
-
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现
public class CommandLine{
public static void main(String args[]){
for(int i=0; i<args.length; i++){
System.out.println("args["+i+"]: "+args[i]);
}
}
}
可变参数
-
JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法
-
在方法声明中,在指定参数类型后加一个省略号(...)
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明
public static void printMax(double... numbers){
if(numbers.length == 0){
System.out.println("No argument passed");
return ;
}
double result = numbers[0];
//求最大值
for(int i=1;i<numbers.length;i++){
if(numbers[i]>result){
result=numbers[i];
}
}
System.out.println("The max value is: "+result);
}
递归
-
A方法调用B方法,我们很容易理解
-
递归就是: A方法调用A方法!就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合
-
递归结构包括两个部分: 1. 递归头: 什么时候不调用自身方法。如果没有头,将陷入死循环 2. 递归体: 什么时候需要调用自身方法
Java数组
数组的定义
1. 数组是相同类型数据的有序集合
2. 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
3. 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们
数组的声明创建
-
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar;// 首选的方法
dataType arrayRefVar[];//效果相同,但不是首选方法 -
Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize];
-
数组的元素是通过索引访问的,数组索引从0开始
-
获取数组的长度: arrays.length
数组的四个基本特点
-
其长度是确定的。数组一旦被创建,它的大小就是不可以改变的
-
其元素必须是相同类型,不允许出现混合类型
-
数组中元素可以是任何类型,包括基本类型和引用类型
-
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员对象
-
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的
数组边界
-
下标的合法区间: [0, length-1],如果越界就会报错
public static void main(String[] args){
int[] a=new int[2];
System.out.println(a[2]);
} -
ArrayIndexOutOfBoundsException: 数组下标越界异常
-
小结:
-
数组是相同数据类型(数据类型可以为任意类型)的有序集合
-
数组也是对象。数组元素相当于对象的成员变量
-
数组长度的确定的,不可变的。如果越界,则报: ArrayIndexOutOfBoundsException
-
多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组
-
二维数组
int a[][]= new int[2][5];
-
解析: 以上二维数组a 可以看成一个两行五列的数组
Arrays类
-
数组的工具类java.util.Arrays
-
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
-
-
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意: 是"不用"而不是"不能")
-
具有以下常用功能:
-
给数组赋值: 通过 fill 方法
-
给数组排序: 通过 sort 方法,按升序
-
比较数组: 通过 equals 方法比较数组中元素值是否相等
-
查找数组元素: 通过 binarySearch 方法能对排序号的数组进行二分查找法操作
-
冒泡排序
package org.example.arrays;
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] array={1,6,4,8,3,9,10,9,10};
bubbleSort(array);
System.out.println(Arrays.toString(array));
}
/**
* 冒泡排序
* @param array
*/
public static void bubbleSort(int[] array){
boolean flag;
for(int i=0;i<array.length-1;i++){
flag=true;
for(int j=0;j<array.length-i-1;j++){
if(array[j]>array[j+1]){
int temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=false;
}
}
if(flag){
break;
}
}
}
}
稀疏数组
-
稀疏数组介绍
-
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组
-
稀疏数组的处理方式是:
-
记录数组一共有几行几列,有多少个不同值
-
把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
-
-
如下图: 上边是原始数组,下边是稀疏数组
0 0 0 22 0 0 15 0 11 0 0 0 17 0 0 0 0 -6 0 0 0 0 0 0 0 0 39 0 91 0 0 0 0 0 0 0 0 28 0 0 0 0 行(row) 列(col) 值(value) [0] 6 7 8 [1] 0 3 22 [2] 0 6 15 [3] 1 1 11 [4] 1 5 17 [5] 2 3 -6 [6] 3 5 39 [7] 4 0 91 [8] 5 2 28 -
-
举例: 原数组转稀疏数组
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 package org.example.arrays;
public class SparseArray {
public static void main(String[] args) {
final int rows=11;
final int cols=11;
// 创建一个二维数组11 * 11 0: 没有棋子 1: 黑棋 2: 白棋
int[][] array=new int[rows][cols];
array[1][2]=1;
array[2][3]=2;
/*for (int[] row : array) {
for (int item : row) {
System.out.print(item+" ");
}
System.out.println();
}*/
int sum=0;
for (int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(array[i][j]!=0){
sum++;
}
}
}
int[][] result=new int[sum+1][3];
result[0][0]=11;//原数组的行数
result[0][1]=11;//原数组的列数
result[0][2]=sum;//原数组中非0个数
int currentIndex=1;//当前存放在稀疏数组的行下标
//遍历二维数组,将非零的值,存放在稀疏数组中
for (int i=0;i<rows;i++){
for (int j = 0; j < cols; j++) {
if(array[i][j]!=0){
result[currentIndex][0]=i;
result[currentIndex][1]=j;
result[currentIndex][2]=array[i][j];
currentIndex++;
}
}
}
//输出稀疏数组
for (int[] row : result) {
for (int item : row) {
System.out.print(item+"\t");
}
System.out.println();
}
}
}
面向对象
面向过程&面向对象
-
面向过程思想
-
步骤清晰简单,第一步做什么,第二步做什么......
-
面对过程适合处理一些较为简单的问题
-
-
面向对象思想
-
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索
-
面向对象适合处理复杂的问题,适合处理需要多人协作的问题
-
-
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理
什么是面向对象
-
面向对象编程(Object-Oriented Programming, OOP)
-
面向对象编程的本质就是: 以类的方式组织代码,以对象的组织(封装)数据
-
抽象
-
三大特性:
-
封装
-
继承
-
多态
-
-
从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
-
从代码运行角度考虑是先有类后有对象。类时对象的模板
创建与初始化对象
-
使用new关键字创建对象
-
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用
-
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
-
必须和类的名字相同
-
必须没有返回类型,也不能写void
-
-
构造器必须掌握
封装
-
该露的露,该藏的藏
-
我们程序设计要追求"高内聚,低耦合"。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合: 仅暴露少量的方法给外部使用
-
-
封装(数据的隐藏)
-
通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏
-
-
记住这句话就够了: 属性私有,get/set
继承
-
继承的本质是对一批类的抽象,从而实现对显示世界更好的建模
-
extends的意思是"扩展"。子类是父类的扩展
-
Java中类只有单继承,没有多继承
-
继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
-
子类和父类之间,从意义上讲应该具有"is a"的关系
-
object类
-
super
-
方法重写
多态
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
-
多态存在的条件
-
有继承关系
-
子类重写父类方法
-
父类引用指向子类对象
-
-
注意: 多态是方法的多态,属性没有多态性
-
package org.example.oop;
public class TestInstanceof {
public static void main(String[] args) {
/*
* Object->String
* Object->Person->Teacher
* Object->Person->Student*/
Object object=new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
System.out.println("--------------------------------------");
Person person=new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);//编译报错
System.out.println("--------------------------------------");
Student student=new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);//编译报错
//System.out.println(person instanceof String);//编译报错
}
}
抽象类
-
abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定是要声明为抽象类
-
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
-
子类继承抽象类,那么就必须实现抽象类没有实现的抽象方法,苟泽该子类也要声明为抽象类
接口
-
普通类: 只有具体实现
-
抽象类: 具体实现和规范(抽象方法)都有
-
接口: 只有规范
-
接口就是规范,定义的是一组规则,体现了现实世界中"如果你是...则必须能..."的思想。如果你是天使,则必须能飞等。
-
接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守
-
OO的精髓,是对对象的额抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象
-
声明类的关键字是class,声明接口的关键字时interface
内部类
-
内部类就是一个类的内部再定义一个类,比如,A类中定义了一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
-
内部类分为:
-
成员内部类
-
静态内部类
-
局部内部类
-
匿名内部类
-
package org.example.oop.innerclass;
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类");
}
//成员内部类
public class Inner{
public void in(){
System.out.println("这是内部类");
}
//获得外部类的私有属性
public void getId(){
System.out.println("获取外部类的私有属性: "+id);
}
}
//静态内部类
public static class StaticInner{
public void in(){
System.out.println("这是静态内部类");
}
}
//局部内部类
public void method(){
class Inner{
public void in(){
System.out.println("这是局部内部类");
}
}
Inner inner = new Inner();
inner.in();
}
}
异常
什么是异常
-
实际工作中,遇到的情况不可能是非常完美的。比如: 你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能就满了。等等。
-
软件程序再运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是: Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
-
异常指程序运行中出现的不期而至的各种状况,如: 文件找不到、网络连接失败、非法参数等。
-
异常发生在程序运行期间,它影响了正常的程序执行流程
异常的体系结构
-
Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
-
在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception
Error
-
Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
-
Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(Jvm)一般会选择线程终止
-
还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况
Exception
-
在Exception分支中有一个重要的子类RuntimeException(运行时异常)
-
ArrayIndexOutOfBoundsException(数组下标越界)
-
NullPointerException(空指针异常)
-
ArithmeticException(算术异常)
-
MissingResourceException(丢失资源)
-
ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理
-
-
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生
-
Error和Exception的区别: Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常
异常处理机制
-
抛出异常
-
捕获异常
-
异常处理的五个关键字
-
try、catch、finally、throw、throws
-
自定义异常
-
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常,只需继承Exception类即可
-
在程序中使用自定义异常类,大体可分为以下几个步骤:
-
创建自定义异常类
-
在方法中通过throw关键字抛出异常对象
-
如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一条操作
-
在出现异常方法的调用者中捕获并处理异常
-
实际应用中的经验总结
-
-
在多重catch块后面,可以加一个catch(Exception)来处理肯恩会被遗漏的异常
-
对于不确定的二代吗,也可以加上try-catch,处理潜在的异常
-
尽量去处理异常,切忌只是简单的调用printStackTrace()去打印输入
-
具体如何处理异常,要根据不同的业务需求和异常类型去决定
-
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!