javaSE学习笔记
前言
1、 什么是Android开发?
Android是一个安装在移动端设备上的操作系统,android应用程序开发(APP)。
2、 为什么要学习Android?
因为Android操作系统使用率最高
3、 如何学习?
Java语言,被公认为是世界上最简单的语言,Java是一种纯面向对象的编程语言。
Android操作系统上运行的程序,都是由Java语言编写的。
学习安排:
第一阶段,JavaSE学习(Java基础学习)40-50天,可以开发简单的桌面应用程序。
第二阶段,android学习,50天左右,可以开发简单的手机应用。
第三阶段,项目实战,便利+ ……
第一部分 Java学习
一、 认识Java编程
1、Java简介
Java的三个分支:
J2SE:Java语法基础、面向对象概念、常用类库、窗体设计、桌面软件;
J2ME:嵌入式开发
J2EE:企业级开发,主要开发管理软件和Web应用。
Java的开发环境
JDK:Java开发的工具包
JRE:Java的开发环境
JVM:Java虚拟机
2、Java开发环境搭建
(1)下载并安装JDK,一路下一步,安装到默认路径;
(2)查看文件夹中是否有内容C:\Program Files\Java,查看
(3)测试是否安装成功,开始键+R,调出运行框口,输入cmd打开DOS命令窗口,在DOS命令窗口中输入java,回车执行,如果有提示,则安装成功
(4)配置环境变量步骤:
第一步:复制路径C:\Program Files\Java\jdk1.8.0_92\bin
第二步:在计算机上点右键,打开“高级系统设置”,选择“高级”选项卡,点击右下角的“环境变量”;
第三步:在系统变量栏中找到“Path”变量,点击编辑;
第四步:在变量值中,末尾处填写:英文输入法的分号 ; ,然后把复制的bin目录路径粘贴,确定保存。
测试环境变量配置成功:调出DOS窗口,运行javac
3、编写第一个Java程序
(1) 在硬盘中新建一个文本文档;
(2) 在文档中编写Java代码,(所有的符号都是英文输入法下编辑的)
public class Hello{ public static void main(String[] args){ System.out.println("智递科技欢迎你!"); } } |
(3) 把文档名,重名为Hello.java
(4) 在此处运行DOS命令
执行:javac Hello.java ,自动创建Hello.class文件;
执行:java Hello ,程序执行,打印输出语句的内容;
注意事项:
(1) class后面的是类名,类名可以自定义,但是要和文件保持一致,使用英文来命名,类名首字母要大写;
(2) 大小写要区分;
(3) 符号要使用英文;
(4) 如果源代码更新,要重新编译(执行javac);
(5) 执行命令,javac编译生成.class文件;java是执行程序,执行的是生成后的.class 文件,不带扩展名;
(6) 在记事本中编辑;
4、Java的运行机制
(1) 通过javac命令,将.java的源代码文件编译为.class的字节码文件(.class字节码文件与操作系统无关,与JVM有关);
(2) 再使用java命令,通过Java虚拟机(JVM)将.class字节码文件解释为特定平台能够识别的机器码;
5、 Java源码书写规范
(1) 在java源文件中,只能有一个使用public修饰的类,源文件名称要和public修饰的类名保持一致;
如果源文件中没有public修饰的类,文件名可以自定义;
(2) 所有类名首字母应为大写(规范),并且类名不能以数字开头;
(3) 类名中只能使用下划线“_” 和美元 “$”,这两种符号;
(4) 在类的内部,还可以继续编写类,称其为内部类;内部类的访问权限与源文件名称无关;
(5) 一个类中只能有一个main方法(即程序的入口),书写的格式是固定;
(6) 在输出语句中,字符串用双引号修饰,如果要进行算术运算,可以直接写数字;
字符串与其他内容拼接时,使用 + 号,如果字符串后面直接跟+号,后面的所有+号默认都是拼接;
拼接的+号后面如果要进行算术运算,可以使用小括号;
(7) 在Java中可以声明变量,变量可以赋值
int 代表整数型,double代表小数型;
(8)Java中的注释:
在程序中对某行或某段代码作解释说明的文本内容,就称为注释。在Java中有三种注释方式:
a.使用 // 双斜杠注释,行内注释
b./*
注释的内容
*/ 多行注释
c.文档注释,使用文档注释的内容,可以生成本地的API文档。
源代码解释:
6、eclipse的使用
(1)选择工作空间
(2)操作窗口
(3)修改文本字体大小
(4)包的命名规范
在项目的src下写源码,类要放在包内,包名的命名规范为当前项目域名的倒置,例如:com.taobao.car
二、Java基础语法
1、标识符
(1)使用在类名、方法名、变量名等需要自定义并且与其他代码或代码块作识别的一种符号标识;
(2)标识符由:数字、字母、下划线“_”、美元$组成;
(3)首字符不能使用数字;
(4)不能使用Java关键字和保留字;
(5)对大小写敏感;
(6)类名的规范:首字母大写,多个单词组合的类名,每个单词的首字母都要大写;
(7)方法名的规范:使用驼峰式写法,多个单词组合的方法名,第一个单词全部小写,从第二单词开始首字母大写;
2、变量的概念
局部变量的存储机制
(1)语法
int a ; //声明变量a a = 1; //为变量a赋值,1 // int a = 1; //简写方式 |
语法规则:
- 先声明、再赋值;
- 没有声明的变量,不能直接赋值;声明后没有赋值的局部变量,不能直接使用;
- 局部变量
(2)变量类型
2 声明在方法体、代码块中的变量称为局部变量;
2 生命周期:从方法执行到该变量声明位置时创建,到方法结束时销毁;
2 只能被final修饰,变为常量;
2 局部变量没有默认值,在使用之前必须要赋值;
- 成员变量(实例变量)
2 声明在类中,在方法体和代码块之外;
2 成员变量有默认值,可以直接使用;
2 成员变量是属于每一个具体实例的(对象的),在类的外部使用时,要用对象来调用;
2 成员变量可以使用访问修饰符修饰,也可以使用非访问修饰符修饰(static、final);
2 通常把成员变量的访问权限设为私有的(private),通过公共的方法对其赋值和取值,这种形式称为封装;
- 类变量
2 使用static关键字修饰的成员变量,被称为类的变量;
2 类变量是属于类所有的,不属于某一个对象,被该类的所有对象共同拥有;
2 类变量既可以使用对象来调用,也可以使用类名来调用;
2 在同类中,类变量可以被静态方法直接调用;
3、基本数据类型
(1)整数型:byte、short、int(默认)、long
public class Test { public static void main(String[] args) { System.out.println("字节类型byte的取值范围:"); System.out.println("长度="+Byte.SIZE); System.out.println("最大值="+Byte.MAX_VALUE); System.out.println("最小值="+Byte.MIN_VALUE); System.out.println("短整型short的取值范围:"); System.out.println("长度="+Short.SIZE); System.out.println("最大值="+Short.MAX_VALUE); System.out.println("最小值="+Short.MIN_VALUE); System.out.println("整数型int的取值范围:"); System.out.println("长度="+Integer.SIZE); System.out.println("最大值="+Integer.MAX_VALUE); System.out.println("最小值="+Integer.MIN_VALUE); System.out.println("长整型long的取值范围:"); System.out.println("长度="+Long.SIZE); System.out.println("最大值="+Long.MAX_VALUE); System.out.println("最小值="+Long.MIN_VALUE); } } |
控制台输出:
字节类型byte的取值范围: 长度=8 最大值=127 最小值=-128 短整型short的取值范围: 长度=16 最大值=32767 最小值=-32768 整数型int的取值范围: 长度=32 最大值=2147483647 最小值=-2147483648 长整型long的取值范围: 长度=64 最大值=9223372036854775807 最小值=-9223372036854775808 |
整数型中的每种类型的取值范围:
Byte型:最大值27-1 ;最小值 -27
Short型:最大值 215-1;最小值 -215
Int型:最大值 231-1;最小值 -231
Long型:最大值 263-1;最小值 -263 ,当值大于int型时,值的末尾要加L
(2)浮点型:
单精度32位 float,默认值是0.0f,当值为整数型时,值的末尾不需要加 f ,当值为小数时,末尾要加 f ;
双精度64位 double(默认)
System.out.println("浮点型float的取值范围:"); System.out.println("长度="+Float.SIZE); System.out.println("最大值="+Float.MAX_VALUE); System.out.println("最小值="+Float.MIN_VALUE); System.out.println("浮点型double的取值范围:"); System.out.println("长度="+Double.SIZE); System.out.println("最大值="+Double.MAX_VALUE); System.out.println("最小值="+Double.MIN_VALUE); |
控制台输出:
浮点型float的取值范围: 长度=32 最大值=3.4028235E38 最小值=1.4E-45 浮点型double的取值范围: 长度=64 最大值=1.7976931348623157E308 最小值=4.9E-324 |
(3)字符型
表示单个字符的一种类型 char,在Java的底层,char类型默认是以int类型进行换算
最大值: ‘\uffff’
最小值: ‘\u0000’
public static void main(String[] args) { char a = ‘A‘-2; int b = 1+‘a‘; System.out.println(b); } |
(4) 逻辑型(布尔型)
布尔型boolean只表示一种结果,值为:true和false,默认值为false
public static void main(String[] args) { boolean b = false;// 假 boolean c = true;// 真 System.out.println(b); System.out.println(c); } |
4、类型转换
(1)强制类型转换(显式转换)
当大类型转小类型时,需要强制类型转换
public static void main(String[] args) { int a = 200; short b = 1; //大类型转小类型,会出现风险 b = (short)a; //赋值,把=号右边变量的值 赋给 =号左边的变量 System.out.println(b); } |
(2)自动类型转换(隐式转换)
当小类型转大类型时,不需要强制类型转换
byte b = 2; int a = 1; a = b; |
(3)int和char类型转换
int ==> char 需要强制类型转换,结果为char类型
int a = 70; char c = ‘B‘; c = (char) a; |
char ==> int 自动类型转换,因为char类型底层是以int进行换算的,结果为int类型
int a = 70; char c = ‘B‘; a = c; |
5、常量
在Java中声明一个不可改变的量,就叫常量,使用final关键字修饰;为了与变量区分,常量名通常要全部使用大写字母;
应用场景:π= 3.14
6、转义字符
7、运算符
(1)算术运算
(2)赋值运算
(3)比较运算
(4)逻辑运算
- &&(短路与)和 &(按位与),都可以作为逻辑运算符,表示“并且”,当两边的值都为true时,结果true,反之为false;
- ||(短路或)和 |(按位或),都可以作为逻辑运算符,表示“或者”,当两个的值有一个为true时,结果为true;
- !(非),结果为值取反;
- &(按位与) 和 |(按位或),除了可以作为逻辑运算符之外,还可以进行位运算;
- 在做位运算时,要先把进行运算的值转为二进制,然后再进行位运算;
&(按位与)运算时,两个值转为二进制,逐位比较,比较的两个值都为1,结果为1;
int a = 5; // 101 int b = 7; // 111 // 结果:101 |
|(按位或)运算时,两个值转为二进制,逐位比较,比较的两个值有一个为1,结果为1;
int a = 10; // 1010 int b = 3; // 0011 //结果:1011 |
当两个字符做位运算时,把字符对应的ASCII码表的十进制数转为二进制,再逐位比较;
char a = ‘A‘; // ASCII-->65 --> 1000001 char b = ‘a‘; // ASCII-->97 --> 1100001 // 结果:1100001 System.out.println(a | b); |
- ^(异或),是作位运算,两边的值先转为二进制,逐位比较,比较的两个值不相等时,结果为1,反之结果为0;
char a = ‘A‘; // ASCII-->65 --> 1000001 char b = ‘a‘; // ASCII-->97 --> 1100001 // 结果:0100000 System.out.println(a ^ b); |
&(按位与)和&&(短路与)的区别:
- 相同点是两个都可以作为逻辑运算符,两边都为true,结果为true;
- 不同点,按位与是两边都判断才计算结果,而短路与在判断第一个条件为false时,就直接计算结果,不再去判断第二个;
- 所以在判断字符串是否为空时,应使用短路与。
示例:
String s = null; if(s!=null && !s.equals("") ){ System.out.println(s); }else{ System.out.println("空"); } |
(5)三目运算
语法:
声明类型 变量名 = 条件 ? 为true的值 : 为false的值 ;
int week = 6; String s = (week>=1 && week <=5) ? "上班" : "打游戏" ; System.out.println(s); |
8、修饰符
Java提供的修饰符由两类:访问修饰符、非访问修饰符。
(1)访问修饰符
- 控制其他类对该类中的属性、方法调用的权限。
- 访问权限有4种,分别是:public(公共的)、protected(受保护的)、default(默认的)、private(私有的)。
- 访问修饰符有3个,分别是:public、protected、private,默认访问权限什么都不写。
- 访问修饰符可以修饰类、实例成员和类的成员;不能修饰局部变量;
- 类只有两种访问权限,分别是public和default;
- 非访问修饰符可以修饰类、属性、方法、代码块,与该类的访问权限无关,是为其修饰的元素增加附加的功能。
- 非访问修饰符有:static、final、abstract、synchronized 和 volatile。
- static 可以修饰成员方法、成员变量、代码块、内部类;当修饰成员方法和成员变量时,该方法和变量就变为了类的方法和类的变量;修饰代码块时,该代码块叫静态代码块,是优先于构造方法执行;
- final 可以修饰类、成员变量、局部变量、成员方法;当修饰变量时,该变量成为常量,必须要赋初始化值,值不能被修改,final修饰成员变量时通常和static配合使用;修饰类时,该类不能被继承;修饰方法时,不能被子类重写;
- abstract可以修饰类和成员方法,用来创建抽象类和抽象方法。
(2)非访问修饰符
三、流程控制
1、分支语句
(1)if-else 分支
语法:
if(判断条件){
满足条件要执行的代码语句;
}
String name = "小明"; int cont ;// 代表成绩的变量 cont = 90; if(cont >= 90 && cont <= 100){ System.out.println(name+"的成绩为:优"); } if(cont >= 80 && cont <90){ System.out.println(name+"的成绩为:良"); } if(cont >= 60 && cont <80){ System.out.println(name+"的成绩为:中"); } if(cont >= 0 && cont <60){ System.out.println(name+"的成绩为:差"); } |
升级版
String name = "小明"; int cont ;// 代表成绩的变量 cont = 90; if(cont >= 90 && cont <= 100){ System.out.println(name+"的成绩为:优"); }else if(cont >= 80 && cont <90){ System.out.println(name+"的成绩为:良"); }else if(cont >= 60 && cont <80){ System.out.println(name+"的成绩为:中"); }else if(cont >= 0 && cont <60){ System.out.println(name+"的成绩为:差"); }else{ System.out.println("输入有误"); } |
(2)switch语句分支
把一个变量与一系列的值进行对比,找到匹配的那一个,然后执行下面的代码,直到遇见break关键字才结束。
int week = 1; switch(week){ case 1: System.out.println("今天是周一"); break; case 2: System.out.println("今天是周二"); break; case 3: System.out.println("今天是周三"); break; case 4: System.out.println("今天是周四"); break; case 5: System.out.println("今天是周五"); break; case 6: System.out.println("今天是周六"); break; case 7: System.out.println("今天是周日"); break; default: System.out.println("输入有误"); } |
Switch使用规则:
a) case后面跟的值的类型,应该与要判断的变量类型保持一致;
b) case后面的值不能重复,并且必须为字面常量或者是常量;
c) switch(x),x的类型可以为:byte、short、int、char,在jdk1.7后,又扩展了String。
2、循环语句
(1)while循环
语法:
While(条件){
满足条件后执行的代码;
}
int a = 0; while(a<10){ a++;// a = a+1 System.out.println("hello:"+a); } |
int a = 0; boolean b = true; while(b){ a++;// a = a+1 System.out.println("hello:"+a); if(a == 5){ b = false; } } |
(2)do-while循环
语法:
do{
要执行的代码;
}while(条件);
与while循环的区别:
do-while当条件不满足时,至少也会被执行一次;
int a = 0; do{ a++;//变量的迭代 System.out.println("a="+a); }while(a<=0); |
(3)for循环
语法:
for(变量声明;条件子句;迭代){
满足条后执行的代码;
}
//变量声明、条件、迭代 for (int i = 1; i < 3;i++ ) { System.out.println("i="+i); } |
(4)跳出循环
- break:跳出当前的循环,继续执行循环下面的代码,可以使用在任何循环和switch语句中;
- continue:结束当前的本次循环,continue后面的代码不会被执行,继续下一次迭代循环;可以使用在任何的循环语句中;
- 跳出多重循环体,可以使用Java的标签,
标签名:(标签名是自定义的)
out: for (int i = 0; i <5;i++ ) { System.out.println("***i="+i+"*****"); for(int j=0; j< 5;j++){ if(j==3){ // break out;//跳出out标签后面的循环 continue out; } System.out.println("j="+j); } } |
四、数组
1、数组的概念
是一组相同类型的数的集合,数组也可以理解为是一个容器;
2、数组的声明
- 方法一
数据类型[] 数组名 = new 数据类型[长度];
// int[] arry = new int[11]; // arry[0] = 1; // arry[1] = 2; // arry[2] = 3; |
赋值和取值都是通过下标来完成
- 方法二
数据类型[] 数组名 = { 值1,值2,值3…… } ;
int[] arry = {1,2,3,4,5,6,7,8,9,10,20,30,40,50,55,60,90}; for(int i = 0 ; i < arry.length ; i++){ System.out.println(arry[i]); } |
取值,可以通过循环来取值
- 方法三
数据类型[] 数组名 = new 数据类型[]{值1,值2,……};
int[] arry = new int[]{1,2,3,4,5,6}; |
3、数组的赋值
a) 通过下标赋值
b) 通过声明方法二的形式,直接赋值
4、数组的遍历
通过循环的方式取得数组中的值,参考声明方法二
5、多维数组
int[] a = {1,2,3,4};//数组中的值的声明语句是int int[] b = {5,6,7,8,9,10}; int[] c = {9,10,11,12,13}; int[][] arry = {a,b,c};//int[] for(int i = 0 ; i < arry.length ; i++){ for(int j = 0 ; j < arry[i].length ; j++){ System.out.print(arry[i][j]+","); } System.out.println(); } |
6、增强for循环
语法:
for(数据类型 标识符 : 数组名){
}
int[] a = {3,1,7,5,4,9,2}; for(int i : a){ System.out.println(i); } |
7、数组排序
(1)冒泡排序
相邻的两个元素对比,交换数据,从后往前依次确定最大或最小值。
int[] a = {3,1,7,5,4,9,2}; for (int i = 1; i < a.length; i++) { for(int j = 0 ; j < a.length - i ; j++){ if(a[j] < a[j+1]){ int temp = a[j]; a[j] = a[j+1]; a[j+1] = temp; } } } System.out.println("排序后:"); for (int i : a) { System.out.print(i+" "); } |
(2)选择排序
第一元素和后面的元素依次对比,交换数据,从前往后依次确定最大或最小值。
int[] a = {3,1,7,5,4,9,2}; for (int i = 0; i < a.length-1; i++) { for(int j = i+1 ; j < a.length; j++){ if(a[i] < a[j]){ int temp = a[i]; a[i] = a[j]; a[j] = temp; } } } System.out.println("排序后:"); for (int i : a) { System.out.print(i+" "); } |
五、面向对象
1、面向对象的概念
对象是指一切客观存在的可见事物和一切不可见事物;
面向对象就是把客观事物在计算机中去创建模型的思想;
对象是由属性和行为组成的;
类就是对象在计算机中的模型;
使用成员变量来表示数据模型(成员属性);
语法:访问修饰 数据类型 属性名
//成员属性-->数据模型 public String name; public String gender; public int age ; |
使用成员方法来表示行为模型;
语法:
访问修饰符 返回值类型(void) 方法名(参数列表){
要执行的代码;
}
//成员方法-->行为模型 // 无参无返回值方法 public void eat(){ System.out.println("吃饭……"); } |
2、类的使用
(1)创建对象(实例化对象)
语法:
类名 对象名 = new 构造器();
//创建对象 Person xw = new Person();//构造器 |
(2)对象赋值
语法:
对象名.属性名;
//创建对象 Person xw = new Person();//构造器 xw.age = 20; xw.name = "小王"; xw.gender = "男"; |
(3)方法调用
语法:
对象名.方法名();
Person p1 = new Person(); p1.name = "张三"; p1.age = 22; p1.gender = "女"; p1.eat(); |
(4)方法参数和返回值
Person类:
public class Person { public String name; public String gender; public double weight; public String jianfei(int i){ return name+"是个"+gender+"胖子体重"+weight+"kg。某天他开始减肥," + "经过不懈努力,减了"+i+"kg。减肥后的体重是"+(weight-i)+"kg。"; } } |
Test类:
Person p1 = new Person(); p1.name = "小王"; p1.gender = "男"; p1.weight = 200; String s = p1.jianfei(40); System.out.println(s); |
3、成员变量和局部变量
区别:
- 成员变量声明在类中,局部变量声明在方法体或代码块内;
- 成员变量作用域在整个类中,局部变量作用在当前的方法体或代码块内;
- 成员变量有初识化值,局部变量没有初始化值,不赋值不能直接使用;
- 当成员变量和局部变量重名的时候,如果直接使用变量名,默认使用的是局部变量,要想使用成员变量,可以加上this关键字;
4、方法重载
原则:
(1) 在同一个类中,声明多个同名的方法;
(2) 方法名相同,参数列表不同,与返回值无关;
(3) 参数列表的个数,类型,类型的顺序不相同;
public class Test { //方法重载 public void a(int j,double i){ } public void a(){ } public void a(double j,int i){ } public void a(int i){ } public static void main(String[] args) { Test t = new Test(); t.a(1); } } |
5、构造方法
构造方法是一个特殊的方法,只有在实例化对象时才会被调用。
语法:
访问修饰符 类名(参数列表){
}
当一个类中没有显式的构造方法,程序在执行的时候会自动创建一个公开的无参的构造方法;
如果类中有一个显式的构造方法,程序在执行时,就不会自动创建公开的无参构造方法;
作用:一般是用于对类中成员变量的赋初始化值;
public class Person { public String name; public int age; //通过构造方法的形式为成员变量赋初始化值 public Person(String name,int age){ this.name = name; this.age = age; } public Person(){ } } |
public static void main(String[] args) { Person p1 = new Person("小明",20); Person p2 = new Person("小王",10); Person p3 = new Person("小李",22); System.out.println(p1.name); System.out.println(p2.name); System.out.println(p3.name); } |
6、this关键字
用法:
(1)是指当前对象;
(2)当局部变量与成员变量名称冲突时,使用this关键字来表示成员变量;
(3)在构造方法中可以调用另一个构造方法,使用this(参数列表)来表示调用构造方法;
public class Person { public String name; public int age; public Person(){ this(1); } public Person(int a){ // this(); this.age = a; } } |
7、static关键字
用法:
(1)static可以直接修饰,成员变量、成员方法、代码块;
(2)使用static关键字修饰的成员变量、成员方法被称为类的变量和类的方法;没有使用static关键字修饰的成员变量、成员方法被称为实例变量和实例方法;
(3)静态成员可以直接调用静态成员,如果调用实例成员,必须要先实例化对象,用具体的对象调用实例成员;
实例成员可以直接调用静态成员和实例成员;
Person类
public class Person { public static String name;//类的 public int age;//实例的,具体对象的 } |
Test类
public void print(){ Person.name = ""; Person p = new Person(); p.age = 1; } |
(4)静态成员是属于类的,所有该类的对象共享静态成员的数据;
Account类
public class Account { public String name; public static double balance; public void qu(double b){ balance -= b; System.out.println(name+"取了"+b+"元,当前余额"+balance+"元"); } public void cun(double b){ balance += b; System.out.println(name+"存了"+b+"元,当前余额"+balance+"元"); } public void print(){ System.out.println(name+"查看,当前余额为"+balance+"元"); } } |
Test类
public static void main(String[] args) { Account wy = new Account(); wy.name = "网银"; Account zfb = new Account(); zfb.name = "支付宝"; Account wx = new Account(); wx.name = "微信"; wy.cun(100); zfb.cun(200); wx.cun(100); wx.qu(300); wy.print(); zfb.print(); wx.print(); } |
(5)static修饰代码块时,该代码块为静态代码块,在类加载的时候先执行,如果有多个静态代码块,按照先后顺序依次执行;一般用于初始化成员变量;
8、访问修饰符
访问修饰符 |
同类 |
同包 |
同包子类 |
不同包 |
不同包子类 |
public |
√ |
√ |
√ |
√ |
√ |
protected |
√ |
√ |
√ |
× |
× |
默认的 |
√ |
√ |
√ |
× |
× |
private |
√ |
× |
× |
× |
× |
9、封装
对属性的封装,私有(private)的属性,公开(public)的方法(getter & setter)
Account类
public class Account { private String id; private String name; private String pwd; private double balance; public void setBalance(double balance){ this.balance = balance; } public double getBalance(){ return balance; } } |
Test类
public static void main(String[] args) { Account a = new Account(); a.setBalance(-20); double d= a.getBalance(); System.out.println(d); } |
10、继承
(1)概念
当多个类中具有相同的属性和行为时,可以把这些相同的元素抽取到一个类中,多个类继承这一个类,就具有了这些元素;
(2)子类的语法
[访问修饰符] class 子类的类名 extends 父类的类名{
}
子类可以继承父类所有非私有的属性和方法;
当父类的方法无法满足子类的需求时,子类可以重写父类的方法;
(3)重写的规则
- 子类重写方法的访问修饰符必须大于等于父类方法的访问权限;
- 声明名部分必须和父类的方法保持一致(返回值,方法名,参数列表);
- 子类继承父类的方法,子类对象调用该方法时,执行的是父类的方法;
- 子类重写父类的方法,子类对象调用该方法时,执行的是子类重写后的方法;
- 子类重写方法抛出的异常范围不能大于父类;
- 在执行子类的构造方法之前,先执行父类的构造方法;
- super()指父类的构造方法,super(参数列表)是指父类的有参构造方法;在子类中如果没有显式的super(),程序执行时会默认创建;
- super()必须在子类的构造方法中第一行执行;
- 在父类中的this关键字,指的是子类的对象;父类中this()指的是当前类的无参构造方法;
- 子类不能继承父类的构造方法;
- 当存在多重继承关系时,先执行最高级别的父类,然后在依次向下执行;
- 在Java中的继承关系是单继承,一个子类只能有一个父类,但是父类可以有多个子类;
- 当父类的属性为子类和父类共同享有时,无论在哪个类中super.属性,this.属性,都是指父类中的那个属性;
(4)子类创建的流程
如果父类和子类具有相同名称的属性,this.属性是指当前类的属性,super.属性是指父类的属性;
11、多态
实现多态的前提:
(1) 具有继承关系;
(2) 子类重写父类方法;
(3) 父类的引用指向子类的对象
语法:
父类类名 引用名 = new 子类构造器();
情景一:
Animal cat = new Cat(); Cat c = (Cat) cat;//cat对象是 Cat类的实例,程序不会出现异常 c.eat(); |
情景二:
Animal cat = new Cat(); Dog d = (Dog) cat;//cat对象不是Dog类的实例,会出现类型转换异常 d.eat(); |
异常信息:
Exception in thread "main" java.lang.ClassCastException: com.zhidi.zoo.Dog cannot be cast to com.zhidi.zoo.Cat |
在对象之间做强制类型转换时,我们要先判断要强转的对象是否为某一类的实例,可以使用instanceof关键字做验证。
示例:
//父类的引用cat,指向子类的对象 cat --> 猫对象 Animal cat = new Cat(); //cat对象如果是Dog类的实例,则返回true,反之返回false if(cat instanceof Dog){ Cat c = (Cat) cat; c.eat(); }else{ System.out.println("类型不匹配"); } |
12、抽象类
(1)概念
- 没有具体的功能,没有方法体的方法就是抽象方法;
- 包含抽象方法的类,一定是抽象类,使用abstract关键字修饰;
- 抽象类和普通类类似,只是多了抽象方法而已;
- 抽象类不能被实例化对象,只能被继承;
- 继承抽象类的子类必须重写抽象类中的所有抽象方法;
- 抽象类可以用于声明;
- 抽象类也可以继承于其他类,成为子类;
(2)语法
抽象方法:
[访问修饰符] abstract 返回值类型 方法名([参数列表]) ;
抽象类:
[访问修饰符] abstract class 类名 [extends 父类]{
}
13、接口
(1)概念
- 接口是定义程序开发中的规范,是更加抽象的抽象类;
- 声明接口是使用interface关键字;
- 接口中只能声明常量和抽象方法,可以省略abstract关键字;
- 接口不能被实例化,只能被类实现,使用implements来实现接口;一个类可以同时实现多个接口;
- 一个接口可以继承另一个或多个接口,成为子接口;
- 接口也是可以被声明为变量的;
(2)语法
[访问修饰符] interface 接口名 [extends 父接口1,父接口2,……] {
[常量];
[抽象方法];
}
14、内部类
(1)成员内部类
声明在类的内部,和外部类的成员属性、成员方法属于同一级别;
public class Outer { //成员属性 public int i = 1; //成员方法 public void print(){ } //成员内部类 public class Inner{ public int i = 2; public void abc(){ System.out.println(Outer.this.i);//指外部类的成员属性i System.out.println(this.i);//指内部类的成员属性i } } } |
实例化内部类:
public static void main(String[] args) { Outer o = new Outer(); Outer.Inner in = o.new Inner();//实例化内部类的对象 in.abc(); } |
(2)静态内部类
声明在类的内部,使用static关键字修饰的类,叫静态内部类。
public class Outer { //静态属性属于类的 public static int i = 0; public int j = 2; //静态方法,是属于类的 public static void print(){ } //静态员内部类 public static class Inner{ public int i = 1; public void abc(){ System.out.println(i);//调用静态内部中的属性 System.out.println(Outer.i);//调用外部类的静态属性 Outer o = new Outer();//调用外部类的非静态属性 System.out.println(o.j); } } } |
实例化静态内部类:
public static void main(String[] args) { Outer.Inner in = new Outer.Inner(); in.abc(); } |
(3)局部内部类
声明在外部类的成员方法或代码块中的类,称为局部内部类,其作用域范围只存在于所处的方法内部,所以只能在其所处的方法中实例化对象。
public class Outer { //成员属性 public int i = 1; //成员方法 public void print(){ int j = 2;//局部变量 //局部内部类 class Inner{ public int i = 3; public void abc(){ System.out.println(i);//指局部内部类Inner的成员属性 System.out.println(Outer.this.i);//指外部类Outer的成员属性 System.out.println(j);//指外部类Outer的print()中的局部变量 } } Inner in = new Inner();//实例化局部内部类对象 in.abc(); } } |
执行局部内部类的方法:
public static void main(String[] args) { Outer o = new Outer(); o.print(); } |
(4)匿名内部类
匿名内部类的声明方式和局部内部类相同,匿名内部类没有类名,实现匿名内部类的前提:必须要继承一个类或实现一个接口。
语法:
new 父类构造器(){
重写父类后的方法;
};
示例:
抽象类Person:
public abstract class Person { public abstract void eat(); } |
匿名内部类:
Person p = new Person(){ @Override public void eat() { System.out.println("吃饭"); } }; p.eat(); |
以上代码,等同于以下代码:
抽象类Person:
public abstract class Person { public abstract void eat(); } |
Man类继承Person:
public class Man extends Person { @Override public void eat() { System.out.println("吃饭"); } } |
测试类:
Person p = new Man(); p.eat(); |
匿名内部类的用途:
一般是用于实例化抽象类和接口的对象。
六、Java常用类库
1、Object类
( 1)toString()方法
Student类:
public class Student { public String name; public int age; public char gender; public Student(String name, int age, char gender) { super(); this.name = name; this.age = age; this.gender = gender; } public Student() { } } |
测试类:
Student s1 = new Student(); s1.name = "张三"; //直接输出对象名,是默认调用的Object类的toString()方法 System.out.println(s1); System.out.println(s1.toString()); //toString()方法返回值的获得详解 String name = s1.getClass().getName();//获得类的全路径; String haxi = Integer.toHexString(s1.hashCode());//得到对象的16进制表示的哈希值 String toString = name+"@"+haxi;//对象的内存地址:对象的全路径 + @ + 16进制哈希值 System.out.println(toString); |
(2)equals()方法
重写Object类的equals()方法,可以对比两个对象内部的属性,通过对比属性来判断两个对象是否表示同一个事物。
2、字符串操作
(1)String类
Character:
char c = ‘A‘; Character ch = new Character(c);//封箱 Character ch1 = Character.valueOf(c);//封箱 System.out.println("是否为数字:"+Character.isDigit(c)); System.out.println("是否为非数字和标点:"+Character.isLetter(c)); System.out.println("是否为空格:"+Character.isWhitespace(c)); System.out.println("是否为大写字母:"+Character.isUpperCase(c)); System.out.println("是否为小写字母:"+Character.isLowerCase(c)); System.out.println("转为大写:"+Character.toUpperCase(c)); System.out.println("转为小写:"+Character.toLowerCase(c)); |
4、Date类
// long time = System.currentTimeMillis(); long time = 1488935537022L; long time2 = 1488935537023L; Date d = new Date(time); Date d2 = new Date(time2); System.out.println(d.before(d2)); |
补充:
//获得时区对象 TimeZone tz = TimeZone.getDefault(); //获得所有时区ID String[] str = TimeZone.getAvailableIDs(); for (String id : str) { //根据时区id来获得此TimeZone对象 TimeZone zone = TimeZone.getTimeZone(id); System.out.println(id+"--->"+zone.getDisplayName()); } //设置时区 TimeZone timzone = TimeZone.getTimeZone("Africa/Abidjan");//获得格林威治时区对象 TimeZone.setDefault(timzone); long time = 0; Date date = new Date(time); System.out.println(date); |
5、日期格式化
long time = 0L; Date d = new Date(time); //按照给定的模式,格式化时间对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String date = sdf.format(d); System.out.println(date); //获得当前时间 System.out.println(sdf.format(new Date())); |
6、Calendar类
//获得日历对象 Calendar c = Calendar.getInstance(); // c.set(2017, 3, 8,12,20,30);//设置时间,如果没有设置时间,默认为当前时间 //添加时间 // c.add(Calendar.MONTH, 100);//如果往后推算,用正数,往前推算用负数 // c.add(Calendar.HOUR_OF_DAY, 20); System.out.println("年:"+c.get(Calendar.YEAR));//年 System.out.println("月:"+(c.get(Calendar.MONTH)+1));//月,从0开始计算 System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH));//日 System.out.println("时:"+c.get(Calendar.HOUR_OF_DAY));//时 System.out.println("分:"+c.get(Calendar.MINUTE));//分 System.out.println("秒:"+c.get(Calendar.SECOND));//秒 System.out.println("星期:"+(c.get(Calendar.DAY_OF_WEEK)-1));//星期(这周的第几天,从周日开始算为第1天) //把日历对象转为Date对象 Date date = c.getTime(); //格式化Date对象 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E HH:mm:ss"); System.out.println(sdf.format(date)); |
获得字段的最大/最小值:
//返回指定字段的最大值 int i = c.getActualMaximum(Calendar.DAY_OF_YEAR); //返回指定字段的最小值 int j = c.getActualMinimum(Calendar.DAY_OF_YEAR); |
格里高利日历对象:
//获得日历对象 Calendar cal = Calendar.getInstance(); //设置指定日历字段的具体值 cal.set(Calendar.YEAR, 2020); //Calendar类中表示年份的字段 int yearField = Calendar.YEAR; //获得当前日历对象中的年份数据 int year = cal.get(yearField); //实例化格里高利日历对象 GregorianCalendar gc = new GregorianCalendar(); //判断Calendar日历对象中的年份是否为闰年 boolean b = gc.isLeapYear(year); if(b){ System.out.println(year+"年是闰年"); }else{ System.out.println(year+"年是平年"); } |
7 、日期解析
//获得一个具体时间 Scanner sc = new Scanner(System.in); System.out.println("请输入一个日期:"); String str = sc.nextLine(); //按照获取的时间格式来设定解析模式 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy"); //解析时间字符串 Date d = sdf.parse(str); System.out.println(d); |
8、正则表达式
正则符号:
含义 |
符号 |
数字 |
[0-9] \\d |
字母 |
[a-zA-Z] |
空白字符 |
[ \n\t\r\f\x0B] |
表示非 |
[^规则] |
任意字符(换行除外) |
. (点) |
正则开始 |
^ |
正则结束 |
$ |
正则数量:
符号 |
含义 |
+ |
n≥1 1到多个 |
* |
n≥0 0到多个 |
? |
0≤ n ≤1 0或1个 |
{n} |
n个 |
{n,} |
n ≤ n到多个 |
{n,m} |
n≤ num ≤m n到m个 |
正则逻辑:
含义 |
符号 |
分组 |
() |
或 |
| |
且 |
什么都不写 |
示例1:
//要验证的字符串 String str = "abc123ABC"; //[]内放的是匹配的规则 boolean b = str.matches("^[a-zA-Z0-9]{6,8}$"); if(b){ System.out.println("匹配"); }else{ System.out.println("不匹配"); } |
示例2:
String str = "abc12bA"; //必须是包含大写、小写、数字,必须以大写字母开头,6-8位 //boolean b = str.matches("^([A-Z])(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{5,7}$"); //必须是包含大写、小写、数字,6-8位 boolean b = str.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])[a-zA-Z0-9]{6,8}$"); if(b){ System.out.println("匹配"); }else{ System.out.println("不匹配"); } |
七、异常处理
1、异常的层级关系
2、常见异常类
(1)ArithmeticException 算术异常
int i,j; i = 1; j = 0; System.out.println(i/j); |
(2)NullPointerException 空指针异常
String s = null; System.out.println(s.toString()); |
(3)ArrayIndexOutOfBoundsException 数组下标越界异常
int[] arr = new int[5]; System.out.println(arr[-5]); |
(4)StringIndexOutOfBoundsException 字符串下标越界异常
String s = "hello"; char c = s.charAt(6); System.out.println(c); |
(5)InputMismatchException 输入不匹配异常
Scanner sc = new Scanner(System.in); int i = sc.nextInt(); System.out.println(i); |
(6)ParseException 解析时异常
Scanner sc = new Scanner(System.in); System.out.println("请输入一个日期:"); String date = sc.nextLine(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date2 = sdf.parse(date); System.out.println(date2); |
(7)ClassCastException 类型转换异常
//父类的引用指向子类的对象,o执行的是Integer对象 Object o = new Integer(1); //可以强转为int类型 // int i = (int) o; //不能再强转为String类型 String s = (String) o; System.out.println(s); |
3、异常处理的方式
(1)使用try-catch-fiannly 语句捕获异常
int i,j; i = 1; j = 0; try{//可能会出现问题的代码 System.out.println(i/j); String s = null; System.out.println(s.toString()); Object o = new Integer(1); String str = (String) o; System.out.println(str); }catch(ArithmeticException e){//捕获相关问题 //解决异常的代码 e.printStackTrace();//打印追踪异常信息 }catch(NullPointerException e){ //解决异常的代码 }catch(Exception e){ //解决异常的代码 }finally{ //无论是否出现异常,finally语句块始终会被执行 } System.out.println("程序结束"); |
注意:当有多个catch语句块时,捕获异常的顺序应该为由小到大,子类异常在前,父类异常在后
(2)使用throws抛出异常
语法:
[访问修饰符] 返回值类型 方法名(参数列表) throws 异常类{
//执行的代码
//存在异常情况的代码语句
}
public static void main(String[] args) { Test t = new Test(); int i = t.abc(1, 0); System.out.println(i); System.out.println("main方法结束"); } //除法运算 public int abc(int cs,int bcs) throws ArithmeticException{ if(bcs == 0){ throw new ArithmeticException("b除数不能为0"); } int rel = cs / bcs; System.out.println("abc方法结束"); return rel; } |
4、自定义异常类
语法:
[访问修饰符] class 类名 extends 异常父类(Exception){
}
public class SuanShuException extends Exception { public SuanShuException(String mess) { super(mess); } } |
使用:
public static void main(String[] args) throws SuanShuException { Test t = new Test(); int i = t.abc(1, 0); System.out.println(i); System.out.println("main方法结束"); } //除法运算 public int abc(int cs,int bcs) throws SuanShuException{ if(bcs == 0){ throw new SuanShuException("b除数不能为0"); } int rel = cs / bcs; System.out.println("abc方法结束"); return rel; } |