一、什么是计算机
- 广泛应用于科学计算、数据处理、自动控制、计算机辅助设计、人工智能、网络领域
- 由硬件和软件组成
二、计算机硬件
计算机硬件的组成:CPU、内存、主板、IO设备、显卡
三、冯诺依曼体系结构
- 冯诺依曼
- 图灵
四、计算机软件
1. 系统软件:DOS、Linux、Windows、Android、iOS
2. 应用软件:WPS、QQ、微信、英雄联盟、绝地求生
五、计算机语言的发展史
更易、更强
第一代语言
- 机器语言
第二代语言
- 汇编语言
- 指令代替二进制
- 解决人类无法读懂机器语言的问题
- 目前应用
- 逆向工程
- 机器人
- 病毒
第三代语言
- 摩尔定律
- 当价格不变时,集成电路上可容纳的晶体管数目,约每隔18个月便会增加一倍,性能也将提高一倍。换而言之,每一美元所能买到的电脑性能,将每隔18个月翻两倍以上
- 高级语言
- 大体上可以分为,面向过程和 面向对象两个大类
- C语言是典型的面向过程的语言。Java、C++是典型的面向对象的语言
- 各种编程语言
- C语言:高级语言的鼻祖
- C++语言
- Java语言:服务器的开发
- C#语言
- Python
- PHP
六、初识Java
Java帝国的诞生
C & C++
- 1972年C语言诞生
- 贴近硬件,运行极快,销量极高
- 操作系统,编译器,数据库,网络系统
- 指针和内存管理
- 1982年C++诞生
- 面向对象
- 兼容C
- 图形领域、游戏等
Java出生
- Java 2 标准版(J2SE):去占领桌面
- Java 2 移动版(J2ME):去占领手机
- Java 2 企业版(J2EE):去占领服务器
Java发展
- 他们基于Java开发了巨多的平台系统和工具
- 构建工具:Ant,maven、Jekins
- 应用服务器:Tomcat,Jetty,Jboos,Websphere,weblogic
- Web开发:Struts,Sprig,myBatis
- 开发工具:Eclipse,IDEA
- 2006年:Hadoop(大数据领域)
- 2008年:Android(手机端)
- 一个伟大的帝国诞生了
java特性和优势
- 简单性
- 面向对象
- 可移植性
- 高性能
- 分布式
- 动态性:反射机制
- 多线程:交互性和实时性
- 安全性
- 健壮性
七、Java的三大版本
- JavaSE 标准版:桌面程序
- JavaME 嵌入式开发:手机、小家电
- JavaEE 企业版:服务器、web端
八、JDK、JRE、JVM
- JDK:Java Development Kit Java开发者工具,包含了JRE和JVM
- JRE:Java Runtime Environment Java运行时环境,包含了JVM
- JVM:Java Virtual Machine Java虚拟机
九、Java开发环境的搭建
- JDK下载与安装
- 配置环境变量
- JDK目录介绍
- Helloworld及简单语法规则
- Notepad++安转和使用
十、java程序运行机制
- 编译型:开发操作系统如C或者C++
- 解释型:网页、服务器边执行边解释对速度的要求不高
理解:美国人如果看中国人写的书,第一种方式,可以翻译成一个英文版,第二种方式,可以找一个翻译官,一遍翻译一遍看。编译型相当于第一种方式,就是把这一本书直接翻译成英文,他会有一个负责翻译的程序,负责翻译的程序叫做编译器;解释型相当于第二种方式。
- 程序的运行机制
十一、IDEA的安装
IDEA就是一种IDE,被誉为最好的Java开发工具之一。
十二、Java基础语法
- 注释、标识符、关键字
- 数据类型
- 类型转换
- 变量、常量
- 运算符
- 包机制、JavaDoc
1、注释
注释并不会被执行,是写个写代码的人看的
-
Java的注释有三种:
- 单行注释://
- 多行注释:
- 文档注释:
public class HelloWorld { public static void main(String[] args) { //单行注释:只能注释一行文字 //输出一个hello System.out.println("hello"); /* 多行注释 我是多行注释,可以注释一段文字 */ /** * 文档注释,可以添加一些东西 * @Author 晁永政 */ } }
2、标识符
- 关键字
注意: String不是关键字,它是一个类。
- Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
标识符的注意点
- 所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始,不能使用数字开头
- 首字母之后可以是字母(A-Z或者a-z),美元符($)、或者下划线(_)或者任何字符组合
- 不能使用关键字作为变量名或者方法名
- 标识符是 大小写敏感的
- 可以使用中文命名,但一般不建议这样做,也不建议使用拼音,很low
String 王者荣耀="百星王者";//没有错,这样写是正确的
3、数据类型
- 强类型语言
- 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
- 弱类型语言
- Java的数据类型分为两大类
- 基本类型
- 引用类型:除了八大基本类型之外都是引用类型,如类、接口、数组
//整数扩展: 进制 二进制0b 十进制 八进制0 十六进制 0x 0~9 A~F
int i = 10;//十进制 1*10的一次方+0*10的0次方
int i2 = 010;//八进制 1*8的一次方+0*8的0次方
int i3 = 0x10;//十六进制 1*16的一次方+0*16的0次方
System.out.println(i);
System.out.println(i2);
System.out.println(i3);
System.out.println("================================================");
//浮点数扩展 银行业务怎么表示?不能用float比较
// BigDecimal 数学工具类
//float 有限 离散 舍入误差 大约 接近但不等于
//double
//最好不使用浮点数进行比较
float f = 0.1f;//flout类型
double d = 1.0/10;//double类型
System.out.println(f);
System.out.println(d);
System.out.println(f==d);//false
float d1=231121316f;
float d2 = d1+1;
System.out.println(d1==d2);//true
输出结果:
4、什么是字节
- 位(bit):是计算机内部数据存储的最小单位,11001100是一个八位二进制数。
- 字节(byte):是计算机中数据处理的基本单位,习惯上用大写B来表示
- 1B(byte,字节)=8bit(位)
- 字符:是指计算机中使用的字母、数字、字和符号。
5、类型转换
- 由于Java是强类型语言,所以要进行有些运算的时候需要用到类型转换
- byte,short,char—> int —>long —> float —>double(由低到高)
- 运算中,不同类型的数据先转换位同一类型,然后进行运算
- 强制类型转换:(类型) 变量名 高到底
- 自动类型转换:低到高
public class Demo05 {
public static void main(String[] args) {
int i = 128;
byte b = (byte)i;//因为byte最大位127,所以下面会出现内存溢出
System.out.println(i);
System.out.println(b);
double d = i;//自动转换
System.out.println(d);
System.out.println((int)23.7);
System.out.println((int)-45.1);
/**
* 注意点:
* 1.不能对布尔类型进行转换
* 2.不能把对象类型转换为不相干的类型 如把一个人转换成一头猪,但可以把一个男人转换成一个女人因为他们都是人
* 3.在高容量转换为低容量的时候
* 4.转换的时候可能存在内存溢出或者精度问题
*/
}
}
运行结果:
public class Demo06 {
public static void main(String[] args) {
//操作比较大的数的时候注意溢出
//JDK7的新特性,数字之间可以用下划线进行分割
int money = 10_0000_0000;
int years = 20;
int total = money*years;//计算的时候已经溢出了
System.out.println(total);
long total2 = money*years;//默认是int,因为money*years这个就是int类型,在这里就已经溢出了,在转换就是转换的溢出之后的结果
System.out.println(total2);
long total3 = money*(long)years;//先把一个数据转换为long类型
System.out.println(total3);
}
}
运行结果:
6、变量
- 变量是什么:变量就是可以变化的量
- Java是一种强类型语言,每个变量都必须声明其类型。
- Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域
- 注意事项
- 每个变量都有类型,类型可以是基本类型,也可是引用类型
- 变量名必须都是合法的标识符
- 变量声明必须是一条完整的语句,因此每个声明都必须以分号结束
7、变量的作用域:
-
类变量
-
实例变量
-
局部变量
public class Demo07 { //属性:变量 //实例变量:从属于对象;通过类来调用,不用进行初始化,会变成该类型的默认值,除了八大基本类型其他的 //默认值都是null String name; int age; //类变量 static int salary = 25000; //main方法 public static void main(String[] args) { //局部变量;必须声明和初始化值,只在这个方法体中有效 int i = 1; System.out.println(i); Demo07 demo07= new Demo07(); demo07.name="cyz"; System.out.println("name="+demo07.name+"\n"+"age="+demo07.age); System.out.println(salary); } //其他方法 public void add(){ } }
8、常量
-
常量:初始化后就不能在改变值!不会变动的值。
-
所谓的常量可以理解成一种特殊的变量,它的值被设定后,在程序运行的过程中不允许被改变
public class Demo09 { //下面两条语句的输出结果相同 //static final是修饰符,和位置无关 static final double PI =3.14; // final static double PI =3.14 public static void main(String[] args) { System.out.println(PI); } }
-
常量一般用大写字符
9、变量的命名规范
- 所有的变量、方法和类名:见名知意
- 类成员变量:首字母小写和驼峰原则,除了第一个单词外其他的首字母大写
- 例:monthSalary、lastName
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母觉下划线
- 例:PI_MAX
- 类名首字母代谢和驼峰原则
- 方法名:首字母小写和驼峰原则
- 例:run()
10、运算符
-
Java支持如下运算符
-
算数运算符:+、-、*、/、%(取余或者模运算)、++、–
long a =23421125152l; int b = 132; short c = 10; byte d =8; System.out.println(a+b+c+d);//long System.out.println(b+c+d);//int System.out.println(c+d);//int /** * 有long的操作为long其余的都是int */ //++ -- 自增,自减 int a =3; System.out.println(a); int b =a++;//a++ a=a+1 a++是在执行完这行代码之后才执行+1,即给b赋值之后才执行+1 System.out.println(b); int c =++a;//a++ a=a+1 ++a是在执行完这行代码之前就执行+1,即给c赋值之前才执行+1 System.out.println(c); //幂运算 2^3 2*2*2=8 很多运算我们会使用工具类来计算 double pow =Math.pow(2,3); System.out.println(pow);
-
赋值运算符:=
-
关系运算符:>、<、>=、<=、==、!=、instanceof
- 关系运算符返回的结果:正确(true)或者错误(false)返回的是布尔值
-
逻辑运算符:&&(与)、||(或)、!(非)
//与(and) 或(or) 非(取反) boolean a = true; boolean b =false; System.out.println("a&&b===="+(a&&b));//逻辑与运算,两变量都为真,结果才为真 System.out.println("a||b===="+(a||b));//逻辑或运算,有一个为真,结果就为真 System.out.println("!(a&&b)===="+!(a&&b));//逻辑非运算,如果为真,则变为假,如果为真就变为假 //短路运算 int c = 5; boolean d =(c<4)&&(c++<4);//因为c<4为假,所以直接返回假,而不会执行c++<4这个操作,所以c也不会自增 System.out.println(d); System.out.println(c);//c依然为4,因为上一步发生短路,并没有执行c++这个操作
-
位运算符:&、|、^、~、>>、<<、<<<(了解)
/**位运算
* A = 0011 1100
* B = 0000 1101
* A&B = 0011 1101
* A|B = 0000 1100
* A^B = 0011 0001
* ~B = 1111 1110
* 28 = 16 2222
* << 左移 相当于*2
* >> 右移 相当于/2
* 0000 0000 0
* 0000 0001 1
* 0000 0010 2
* 0000 0100 4
* 0000 1000 8
* 0001 0000 16
* 效率极高
*/
System.out.println(2<<3);//结果为16- 条件运算符:?、: ~~~java //+:字符串连接符 //只要有一方为字符串结果就位字符串 int a =10; int b =20; System.out.println("string"+a+b);//结果为string1020 System.out.println(a+b+"string");//结果为30string //以上两个输出的都是String类型的 /** * 三元运行符 * x ? y : z * 如果x为真结果为y,如果x结果假,结果为z * 必须掌握 */ System.out.println(80<60?"不及格":"及格");//输出及格
- 扩展赋值运算符:+=、-=、*=、/=
Java运算符的优先级:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cbKzG5Zs-1644305038014)(C:/Users/晁永政/AppData/Roaming/Typora/typora-user-images/image-20210416214752927.png)]
-
11、包机制
本质就是相当于Windows的文件夹
-
为了更好的组织类,Java提供了包机制,用于区别类名的命名空间
-
包机制的语法格式为
package pkg1[.pkg2...]
-
一般利用公司的域名作为包名
-
为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用import语句可以完成此功能
import packge1[.packge2...].(classname|*);//*代表通配符,导包中的所有的类
12、JavaDoc
-
javadoc命令是用来生成自己的API文档的
-
参数信息
-
@autor 作者名
-
@version 版本号
-
@since 致命指明需要最早的JDK版本
-
@param 参数名
-
return 返回值情况
-
throws 异常抛出情况
-
十三、java流程控制
1、用户交互Scanner
通过Scanner类来获取用户的输入
基本语法:
Scanner s = new Scanner(System.in)
- 通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取之前我们一般需要使用hasNext()和hasNextLine()判断是否还有输入的数据
package com.wwm.Scanner;
import java.util.Scanner;
public class Demo01 {
public static void main(String[] args) {
//创建一个扫描对象,System.in用于接收数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方法接收:");
//判断用户有没有输入字符串
if (scanner.hasNext()){
//使用next方法接收
String str = scanner.next(); //程序会等待用户输入
System.out.println("输入的内容为:"+str);
}
//凡是属于IO流的类如果不关闭会一直占用资源,要养成好习惯用完就关掉
//IO流即输入输出流
scanner.close();
}
}
/*
输入 hello world
输出 hello
*/
package com.wwm.Scanner;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方法接收:");
if(scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println("输出的内容为:"+str);
}
scanner.close();
}
}
/*
输入 hello world
输出 hello world
*/
next():
一定要读取得到有效字符后才可以结束输入
对输入有效字符之前遇到的空白,next()方法会自动将其去掉
只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
==next()==不能得到带有空格的字符串
nextLine():
以Enter为结束符,也就是说nextLine()方法返回的是输入回车键之前的所有字符
可以获得空白
package com.wwm.Scanner;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数据:");
String str = scanner.nextLine();
System.out.println("输入的内容为:"+str);
scanner.close();
}
}
/*
输入:欢迎学习狂神说java 欢迎大家来到线下学习
输出:欢迎学习狂神说java 欢迎大家来到线下学习
*/
package com.wwm.Scanner;
import java.util.Scanner;
public class Demo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//从键盘接收数据
int i = 0;
float f = 0.0f;
System.out.println("请输入整数:");
//如果。。。那么。。。。
if (scanner.hasNextInt()){
i = scanner.nextInt();
System.out.println("整数数据:"+ i );
}else{
System.out.println("输入的不是整数数据!");
}
System.out.println("请输入小数:");
if (scanner.hasNextFloat()){
f = scanner.nextFloat();
System.out.println("小数数据:"+f);
}else{
System.out.println("输入的不是小数数据!");
}
scanner.close();
}
}
package com.wwm.Scanner;
import java.util.Scanner;
public class Demo05 {
public static void main(String[] args) {
//我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果:
Scanner scanner = new Scanner(System.in);
//和
double sum = 0;
//计算输入了多少数字
int m = 0;
//通过循环判断是否还有输入,并在里面对每一次进行求和和统计
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
m = m+1;//m++
sum = sum + x;
System.out.println("你输入了"+m+"个数据,当前结果sum"+sum);
}
System.out.println(m + "个数的和为" + sum);
System.out.println(m + "个数的平均值是" + (sum / m));
scanner.close();
}
}
2、顺序结构(java的基本结构)
- java的基本结构就是顺序结构,除非特别指明,否则就要按照顺序一句一句执行。
- 顺序结构是最简单的算法结构
- 语句与语句之间是从上到下的顺序进行的啊,他是由若干个一次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构
package com.wwm.struct;
public class ShunXu {
public static void main(String[] args){
System.out.println("hello1");
System.out.println("hello2");
System.out.println("hello3");
System.out.println("hello4");
}
}
3、if选择结构
1、if单选择结构:
if(布尔表达式){
//操作
}
package com.wwm.struct;
import java.util.Scanner;
public class ifDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容:");
String s = scanner.nextLine();
//equals:判断字符串是否相等
if(s.equals("Hello")){
System.out.println(s);
}
System.out.println("End");
scanner.close();
}
}
2、if双选择结构:
语法:
if(布尔表达式){
//如果表达式的值为true
}else{
//如果布尔表达式的值为false
}
package com.wwm.struct;
import java.util.Scanner;
public class ifDemo02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//考试分数大于60及格
System.out.println("请输入成绩:");
int score = scanner.nextInt();
if(score>60){
System.out.println("及格");
}else{
System.out.println("不及格");
}
scanner.close();
}
}
3、if多选择结构
if (布尔表达式1){
//如果布尔表达式1为true将执行的语句
}else if (布尔表达式2){
//如果布尔表达式2为true将执行的语句
}else if (布尔表达式2){
//如果布尔表达式3为true将执行的语句
}else{
//如果布尔表达式全部为false将执行的语句
}
package com.wwm.struct;
import java.util.Scanner;
public class IfDemo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入成绩:");
int score = scanner.nextInt();
if(score==100){
System.out.println("恭喜满分!");
}else if(score<100 && score>=90){
System.out.println("A级");
}else if(score<90 && score>=80){
System.out.println("B级");
}else if(score<80 && score>=70){
System.out.println("C级");
}else if(score<70 && score>=60){
System.out.println("D级");
}else if(score<60 && score>=0){
System.out.println("不及格");
}else{
System.out.println("输入数据不合法!");
}
scanner.close();
}
}
注意点:
-
if语句至多有一个else语句,else语句在所有的else if语句之后
-
if语句可以有若干个elae if 语句,他们必须在else语句之前
一旦其中一个else if 语句检测为true,其他的else if 以及else语句都将跳过执行
4、嵌套的if语句
语法:
if(布尔表达式1){
//如果布尔表达式1的值为true执行代码
if(布尔表达式2){
//如果布尔表达式2的值为true执行代码
}
5、switch多选择结构
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
switch(expression){
case value1:
//case
break;//不写会把后面的全部输出(case穿透现象)
case valuse2:
//case
break;
default://可选
//default case
}
switch 语句中的变量类型可以是:
- byte、short、int、或者char
- 从java SE 7开始
- switch支持字符串String类型了
- 同时case标签必须为字符串常量或字面量
package com.wwm.struct;
public class SwitchDeom01 {
public static void main(String[] args) {
//
char grade = 'C';
switch (grade){
case 'A':
System.out.println("优秀");
break; // 可选,如果没有break,会持续往下执行语句,这种现象就case穿透
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("再接再厉");
break;
case 'E':
System.out.println("挂科");
break;
default:
System.out.println("数据错误!");
}
}
}
package com.wwm.struct;
public class SwitchDemo02 {
public static void main(String[] args) {
String name = "秦疆";
//jdk7之后才可以
switch (name){
case "秦疆":
System.out.println("秦疆");
break;
case "狂神":
System.out.println("狂神");
break;
default:
System.out.println("弄啥类!");
}
}
}
- 字符的本质还是数字
- 反编译 java—class(字节码文件) ----反编译(IDEA)
4、循环结构
1、while循环
while(布尔表达式){
//循环内容
}
只要布尔表达式为true,循环就会一直执行下去
我们大多数情况下会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环
少部分情况需要循环一直执行,比如服务器的请求响应监听等
循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环,会影响程序性能或者造成程序卡死崩溃
package com.wwm.struct;
public class WhileDemo01 {
public static void main(String[] args) {
//输出1~100
int i = 0;
while(i<100){
i++;
System.out.println(i);
}
}
}
package com.wwm.struct;
public class WhileDemo03 {
public static void main(String[] args) {
//计算1+2+3++++100=?
//高斯的故事
int i = 0;
int sum = 0;
while(i<100){
i++;
sum = sum +i;
}
System.out.println(sum);
}
}
2、do···while循环
对于while语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件。也至少执行一次
do···while循环和while循环相似,不同的是,do···while循环至少会执行一次
do{
//代码语句
}while(布尔表达式);
while和do-while的区别:
while先判断后执行,do-while是先执行后判断
do-while总是保证循环体会被至少执行一次,这是他们的主要差别
3、 for循环
-
虽然所有循环结构都可以用while或者do···while表示,但java提供了另一种语言——for循环,使一些循环结构变得更加简单
-
for循环是支持迭代的一种通用语言,是最有效、最灵活的循环结构
-
100.for可快速形成for循环结构
for(初始化;布尔表达式;更新){
//代码语句
}
package com.wwm.struct;
public class ForDemo01 {
public static void main(String[] args) {
int a = 1; //初始化条件
while(a<=100){ //条件判断
System.out.println(a); //循环体
a+=2; //迭代
}
System.out.println("while循环结束!");
//初始化值 条件判断 迭代
for(int i = 1;i<=100;i++){
System.out.println(i);
}
// 100.for可快速形成for循环结构
// for (int j = 0; j < 100; j++) {
//
// }
System.out.println("for循环结束");
}
}
注意点:
最先执行初始化步骤,可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句
然后,检测布尔表达式的值,如果为true,循环体被执行,如何为false,循环终止,开始执行循环体后面的语句
执行一次循环后,更新循环循环变量(迭代因子控制循环变量的增减)
再次检测布尔表达式,循环执行上面的过程
分别移出三个步骤:但变量需提前初始化
for (; a < 3; a++) {
System.out.println(a);
}
for (; true; b++) {
if (b >= 3) {//满足条件跳出循环
break;
}
for (; true;) {
if (c >= 3) {//满足条件跳出循环
break;
}
package com.wwm.struct;
/**
* 计算0到100之间的奇数和偶数的和
*/
public class ForDemoQuestion01 {
public static void main(String[] args) {
int a = 0;
int sum1 = 0;
int sum2 = 0;
for(;a<=100;a++){
if(a==1){
sum2 = sum2 +1;
}else{
if(a%2==0){
sum1 = sum1+a;
}else{
sum2 = sum2+a;
}
}
}
System.out.println("偶数和为"+sum1);
System.out.println("奇数和为"+sum2);
}
}
package com.wwm.struct;
public class ForDemoQuestion02 {
/**
* 1000 之能被5整除的数
*/
public static void main(String[] args) {
int a = 1;
int b = 0;
for(;a<=1000;a++){
if(a>=5){
if(a%5==0){
b++;
if(b==3){
System.out.println(a+" ");
b=0;
}else{
System.out.print(a+" ");
}
}
}
}
}
}
package com.wwm.struct;
/**
打印九九乘法表
*/
public class ForDemoQuestion03 {
public static void main(String[] args) {
//1.我们先打印第一列
//2.我们把固定的1再用一个循环都包起来
//3.去掉重复项
//4.调整样式
for (int j = 1; j <= 9; j++) {
for (int i = 1; i <=j;i++) {
System.out.print(j+"*"+i+"="+(j*i)+"\t");
}
System.out.println();
}
}
}
4、增强for循环
数组之后重点使用
java5引入了一种主要用于数组或集合的增强型for循环
java增强for循环语法格式:
for(声明语句:表达式){
//代码句子
}
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配其作用域限定在循环语句块,其值于此时数组元素的值相等
表达式:表达式是要访问的数组名,或者是返回值为数组的方法
package com.wwm.struct;
public class ForDemo05 {
public static void main(String[] args) {
int[] numbers = {10,20,30,40,50}; //定义了一个数组
for(int i = 0;i<5;i++){
System.out.println(numbers[i]);
}
System.out.println("=========================");
//遍历数组元素
for(int x:numbers){
System.out.println(x);
}
}
}
5、break continue
break在任何循环语句的主体部分,均可使用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break语句也可再switch语句中使用)
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下次是否执行循环的判定
关于goto关键字
goto关键字很早就在程序设计语言中出现,尽管goto仍是java的一个保留字,但并未在语言中正式得到使用;java没有goto。然而,在 break和continue这两个关键字的身上,我们仍能看出一些goto的影子—带标签的break和continue
标签是指后面跟一个冒号的标记符,例如:label
对java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环名单若随标签使用,他们就会中断到存在标签的地方。
break在任何循环语句的主体部分,均可用break控制循环的流程
break用于强行退出循环,不执行循环中剩余的语句(break语句也在switch语句中使用)
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定
十四、java方法详解
1、何谓方法?
-
System.out.println(),那么它是什么呢?
//System"类".out“输出对象”.println()“方法”
- Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
- 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
- maim尽量干净简洁,把公共模块提取到外面,利用方法调用。
- 回顾:方法的命名规则?首字母小写,驼峰命名规则
加法练习:
public static void/*代表空类型*/ main(String[] args) { //实际参数,实际调用传输给他的参数 int sum = add(1,2); System.out.println(sum); }//形式参数,用来定义作用的 public static int/*返回类型*/ add(int a,int b){ return a+b;//返回值 }
- Java方法是语句的集合,它们在一起执行一个功能。
2、方法的定义
-
Java的方法类似于其它语言的函数,是==一段用于完成特定功能的代码片段,==一般情况下,定义一个方法包含以下语法
-
==方法包含一个方法头和一个方法体。==下面是一个方法的所有部分:
-
**修饰符:**修饰符,这是可以选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
-
**返回值类型:**方法可能会返回值,returnValueType 是方法返回值的数据类型,有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
-
**方法名:**是方法的实际名称。方法名和参数表共同构成方法签名。
-
**参数类型:**参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
-
**方法体:**方法体包含具体的语句,定义该方法的功能。
修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
- 返回值:return可以返回值,也可以结束程序。java只有值传递
public static void main(String[] args){ max(20,20); } public static int max(int num1, int num2){ int result = 0; if (num1==num2){ System.out.println("数据相等"); return 0; } if (num1>num2){ result = num1; System.out.println(result); } if (num2>num1){ result = num2; System.out.println(result); }return result; }
-
3、方法重载
-
重载就是在一个类中,有相同的函数名称,但形参不同的函数。
-
方法重载的规则:
- 方法名称必须相同。
- 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
- 方法的返回类型可以相同也可以不相同。
- 仅仅返回类型不同不足以成为方法的重载。
-
实现理论:
-
方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
public static void main(String[] args) { max(11,11,11); } //二整数比大小 public static int max(int max1,int max2){ int result = 0; if (max1==max2){ System.out.println("两值相等"); return 0; }if (max1>max2){ result = max1; System.out.println(result); }if (max2>max1){ result = max2; System.out.println(result); }return result; } //二小数比大小 public static double max(double max1,double max2){ double result = 0; if (max1==max2){ System.out.println("两值相等"); return 0; }if (max1>max2){ result = max1; System.out.println(result); }if (max2>max1){ result = max2; System.out.println(result); }return result; } //三小数比大小 public static double max(double max1,double max2,double max3){ double result = 0; if (max1==max2 && max2==max3){ System.out.println("两值相等"); return 0; }if (max1>max2 && max1>=max3){ result = max1; System.out.println(result); } else if (max1>max3 && max1>=max2){ result = max1; System.out.println(result); } else if (max2>max1 && max2>=max3){ result = max2; System.out.println(result); }else if (max2>max3 && max2>=max1){ result = max2; System.out.println(result); }else if (max3>max1 && max3>=max2){ result = max3; System.out.println(result); }else if (max3>max2 && max3>=max1){ result = max3; System.out.println(result); }return result; }
-
4、命令行传参
-
有时候你希望运行一个程序时候再传递给他消息。这要靠传递命令行参数给main()函数实现。
public static void main(String args[]){ for(int i=0;i<args.length;i++){ System.out.println("args["+i+"]:"+agrs[i]) } }
5、可变参数
- JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。
- 在方法声明中,在指定参数类型后加一个省略号(…)。
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
public static void main(String[] args) {
printMax(34,3,3,2,56.5);
printMax(new double[]{1,2,3});
}
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);
}
6、递归
-
A 方法调用 B 方法,我们很容易理解!
-
递归就是:A 方法调用 A 方法!就是自己调用自己
-
利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可貌似出解决过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分:
- 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
- 递归体:什么时候需要调用自身方法。
-
递归适合小计算,如果太大量计算容易内存崩溃,死机。
public static void main(String[] args){ //5的阶层 System.out.println(f(5)); } public static int f(int n){ if (n==1){ return 1; }else { return n*f(n-1); } }
# 十五、数组
## 1、数组的定义
- 数组是相同类型数据的有序集合。
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
## 2、数组声明创建
- **首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:**
~~~java
//声明的方式
dataType[] arrayRefVar; // 首选的方法
或
dataType arrayRefVar[]; // 效果相同,但不是首选方法
- Java 语言使用 new 操作符来创建数组,语法如下:
ataType[] arrayRefVar = new dataType[arraySize];//分配数组空间
- 数组的元素是通过索引访问的,数组索引从0开始
- 获取数组长度:
arrays.length
练习:
public static void main(String[] args){
int[] nums; //1.首选声明一个数组
nums = new int[10]; //2.创建一个数组
//3.给数组元素中赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 5;
nums[5] = 6;
nums[6] = 7;
nums[7] = 8;
nums[8] = 9;
nums[9] = 10;
//计算所有元素的和
int sum = 0;
//获取数组长度:arrays.length
for (int i = 0; i < nums.length ; i++){
sum = sum + nums[i];
}
System.out.println("总和:"+sum);
}
3、内存分析
- Java内存分析:
4、三种初始化
- 静态初始化
//静态初始化:创建 + 赋值
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
- 动态初始化
//动态初始化:包含默认初始化,未赋值前为0。
int[] a = new int[2];
a[0] = 1;
a[1] = 2;
- 数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方法被隐式初始化。
5、数组的四个基本特点
-
其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
-
其元素必须是相同类型,不允许出现混合类型。
-
数组中的元素可以是任何数据类型,包括基本类型和引用类型。
-
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,
数组对象本身是在堆中的。
6、数组边界
-
下标的合法区间:[0,length-1],如果越界就会报错;
public static void main(String[] args){ int[] a=new int[2]; //a长度为2,下标表示为a[0],a[1]. System.out.println(a[2]);//a[2]以超出设定值 }
- ArraylndexOutOfBoundsException:数组下标越界异常!
- 小结:
- 数组是相同数据类型(数据类型可以为任意类型)的有序集合
- 数组也是对象。数组元素相当于对象的成员变量
- 数组长度的确定的,不可变的。如果越界,则报:ArrayindexOutofBounds
7、数组的使用
-
普通的For循环
-
For-Each 循环
-
数组作方法入参
-
数组作返回值
练习:
public static void main(String[] args) { int[] arrays = {11,12,13,14,15}; //打印全部的数组元素 for (int i = 0 ; i<arrays.length ; i++){ System.out.println(arrays[i]); } System.out.println("===================="); //打印数组元素之和 int sum = 0; for (int i = 0; i < arrays.length; i++) { sum = sum +arrays[i]; } System.out.println("sum="+sum); System.out.println("================="); //查找数组内最大元素 int max = arrays[0] ; for (int i = 1; i < arrays.length; i++) { if (max < arrays[i]){ max = arrays[i]; } } System.out.println("max="+max); }
public static void main(String[] args) { int[] arrays ={1,2,3,4,5}; //JDK1.5 没有下标 for (int array : arrays) { System.out.print(array+" "); } System.out.println(); System.out.println("打印数组"); printArray(arrays); System.out.println("反转数组:"); int[] reverse= reverse(arrays); printArray(reverse); } //反转数组 public static int[] reverse(int[] arrays){ int[] reverse =new int[arrays.length]; for (int i = 0, j=reverse.length-1; i <arrays.length; i++,j--) { reverse[j] = arrays[i]; } return reverse; } //打印数组元素 public static void printArray(int[] arrays){ for (int i = 0; i <arrays.length ; i++) { System.out.println(arrays[i]+" "); } }
8、多维数组
-
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
-
二维数组
int a[][] =new int[2][5];
-
解析:以上二维数组 a 可以看成一个两行五列的数组。
-
思考:多维数组的使用?
num[1][0];
练习:
public static void main(String[] args) {
int[][] array = {{1,2},{2,3},{3,4},{4,5}};
for (int i = 0; i <array.length ; i++) {
for (int j = 0; j <array[i].length ; j++) {
System.out.print(array[i][j]+" ");
}
}
}
9、Arrays 类
- 数组的工具类java.uti.Arrays
- 由于数组对象本身并没有什么方法可以供我们调用,但是 API 中提供了一个工具类 Arrays 供我们使用,从而可以对数据对象进行一些基本的操作。
- 查看 JDK 帮助文档
- Arrays 类中的方法都是 static 修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
- 具有以下常用功能:
- 给数组赋值:通过 fill 方法。
- 对数组排序:通过 sort 方法,按升序。
- 比较数据:通过 equals 方法比较数组中元素值是否相等。
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
public static void main(String[] args) {
int[] a = {3,54,8,2,9,6,57,12,87};
//打印数组元素,Arrays.toString
System.out.println(Arrays.toString(a));
//数组排序操作
Arrays.sort(a);
System.out.println(Arrays.toString(a));
//数组填充
Arrays.fill(a,7);
System.out.println(Arrays.toString(a));
//选择填充
Arrays.fill(a,2,6,0);
System.out.println(Arrays.toString(a));
}
10、冒泡排序
- 冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
- 冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。
- 我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为o(n2)。
public static void main(String[] args) {
int[] a = {23,5,6,76,8,1,2,9,34,76};
int[] dai = dai(a);
System.out.println(Arrays.toString(a));
}
public static int[] dai(int[] suzu){
int p = 0;
boolean flag = false;
for (int i = 0; i <suzu.length-1 ; i++) {//最大外循环
for (int j = 0; j <suzu.length-1-i ; j++) {//排序循环
if (suzu[j+1]<suzu[j]){
p = suzu[j];
suzu [j] = suzu[j+1];
suzu [j+1] = p;
flag = true;
}if (flag == false){//优化,提前结束。
break;
}
}
}return suzu;
}
11、稀疏数组
- 需求:编写五子棋游戏中,有存盘退出或续上盘的功能。
- 分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据。
- 解决:稀疏数组
稀疏数组介绍
-
当一个数组中大部分元素为0,或者为同一值得数组时,可以使用稀疏数组来保存该数组。
-
稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值。
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
public static void main(String[] args) { int[][] array1 = new int[11][11];//0代表空,1代表黑子,2代表白子 array1[1][2] = 1;//给黑子定位 array1[2][3] = 2;//给白子定位 //输出原始数据 System.out.println("原始数据:"); for (int[] ints : array1) { for (int anInt : ints) { System.out.print(anInt+" "); } System.out.println(); } System.out.println("======================"); //转换为稀疏数组保存 //1.求和有效值的个数 int sum = 0; for (int i = 0; i < array1.length; i++) { for (int j = 0; j < array1.length; j++) { if (array1[i][j]!=0){ sum++; } } } System.out.println("稀疏数组:"); //2.创建一个稀疏数组的数组 int[][] array2 = new int [sum+1][3];//确定第一条稀疏数组的数据 array2[0][0]= 11; array2[0][1]= 11; array2[0][2]= sum; //3.将非零的值,存放在稀疏数组中 int count = 0; for (int i = 0; i <array1.length ; i++) { for (int j = 0; j <array1.length ; j++) { if (array1[i][j] != 0){ count++; array2[count][0] = i; array2[count][1] = j; array2[count][2] = array1[i][j]; } } } System.out.println("序 "+" 行 "+" 列 "+" 值 ");//打印数组 int xu = 0; for (int[] ints : array2) { System.out.print(xu+" "); for (int anInt : ints) { if (anInt<10){System.out.print(" "+anInt+" ");} else { System.out.print(" "+anInt+" ");} } xu++; System.out.println(); } /* for (int i = 0; i <array2.length ; i++) { System.out.println(array2[i][0]+"\t" +array2[i][1]+"\t" +array2[i][2]+"\t"); }*/ System.out.println("========================"); //转换成原始数据 System.out.println("还原原始数组:"); int[][] array3 = new int[array2[0][0]][array2[0][1]];//确认原始数组整体大小 for (int i = 1; i <array2.length ; i++) { array3[array2[i][0]][array2[i][1]]=array2[i][2];//将数组的数据赋值 } for (int[] ints : array3) { for (int anInt : ints) { System.out.print(anInt+" "); } System.out.println(); } }
十五、面向对象编程
1、初识面向对象
面向对象&面向过程
- 面向过程思想
- 步骤清晰简单,第一部做什么,第二部做什么……
- 面对过程是和处理一些较为简单的问题。
- 面向对象思想
- 物以类聚,分类的思维模式,思维问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象是和处理复杂的问题,适合处理需要多人协作的问题!
- 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思想类分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
- 面向对象编程(Object-Oriented Programming,OOP)
- 面向对象编程的本身就是:以类的方式组织代码,以对象的组织(封装)数据。
- 抽象
- 三大特性:
- 封装
- 继承
- 多态
- 从认识论的角度考虑是先有对象后有类。对象,是具体的食物。类,是抽象的,是对对象的抽象。
- 从代码运行角度考虑是现有类后有对象。类是对象的模板。
2、方法回顾和加深
- 方法的定义
- 修饰符
- 返回类型
- break:跳出 switch,结束循环 和 return 的区别
- 方法名:注意规范就OK 见名知义
- 参数列表:(参数类型,参数名)……
- 异常抛出:疑问,后面讲解
- 方法的调用:递归等
- 静态方法
- 非静态方法
- 形参和实参
- 值传递和引用传递
- this关键字
package oop.Demo01;
import java.io.IOException;
//Demo01 类
public class Demo01 {
//方法
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名(......){
//方法体
return 返回值;
}
*/
//return 结束方法,返回一个结果
public String saayhello(){
return "hello,world";
}
//void返回一个空或者什么都不返回
public void hello(){
return;
}
public int max(int a,int b){
return a>b?a:b; //三元运算符!
}
//数组下表越界
public void readFile(String file) throws IOException{
}
}
package oop.Demo01;
public class Demo02 {
//静态方法 static
//非静态方法
public static void main(String[] args) {
//实例化这个类 new
// 对象类型 对象类型=对象值;
Student student = new Student();
student.say();
}
//和类一起加载的
public static void a() {
//b();
}
//类通过new实例化之后 才存在的
public void b() {
}
//b可以调用a,a不能调用b
//都有或者都没static的话,可以相互调用
}
package oop.Demo01;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a=1;
System.out.println(a);//1
Demo04.change(a);
System.out.println(a);//1
}
//返回值类型
public static void change(int a) {
a=10;
}
}
package oop.Demo01;
//引用传递:对象,本质还是值传递
//对象 内存
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //null
Demo05.change(person); //此处person被传递过来
System.out.println(person.name); //秦疆
}
public static void change(Person person) {
//person是一个对象:指向的是---》 Person person = new Person();这是一个具体的人,可以改变属性
person.name="秦疆"; //修改了class中的name
}
}
//定义了一个Person类,有一个属性:name
class Person{
String name;
}
类与对象的关系
- 类是一种抽象的数据类型,它是对某一类事物整体的描述/定义,但是并不能代表某一个具体的事物。
- 动物、植物、手机、电脑…
- Person类、Pet类、Cat类等,这些都是用来描述/定义某一类具体的事物应该具备的特点和行为.
- 对象是抽象概念的具体实例.
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例.
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念.
创建与初始化对象
-
使用new关键字创建对象。
-
使用new关键字创建时,除了分配内存空间之外,还会给创建好的对象进行默认化以及对类中构造器的调用。
-
类中构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同。
- 必须没有返回类型,也不能写void。
-
构造器必须要掌握.
package oop.Deno02; //学生类 public class Student { //属性:字段 String name;//默认值null int age;//默认值0 //方法1 public void study(){ System.out.println(this.name+"在学习"); } }
package oop.Deno02; //一个项目只能有一个main方法 public class Application { public static void main(String[] args) { //类:抽象的,实例化 //类实例化后会返回一个自己的对象! //student对象就是一个Student类的具体实例! Student xiaoming = new Student(); Student xh = new Student(); xiaoming.name = "小明"; xiaoming.age = 3; System.out.println(xiaoming.name); System.out.println(xiaoming.age); xh.name="小红"; xh.age=3; System.out.println(xh.name); System.out.println(xh.age); } }
package oop.Deno02; //java-->class public class Person { //一个类即使什么都不写,他也会存在一个方法 //显示的定义构造器 String name; int age; //alt+insert快捷键,生成构造器 //1.使用new关键字,本质在于调用构造器 //2.用来初始化值 //无参构造 public Person(){} //有参构造:一旦定义了有参构造,无参构造必须显示定义 public Person(String name,int age){ this.name=name; this.age=age; } }
package oop.Deno02; public class Application02 { public static void main(String[] args) { //new实例化了一个对象 Person person = new Person("kuangshen",23); System.out.println(person.name); System.out.println(person.age); } } /* public class Application02 { public static void main(String[] args) { //new实例化了一个对象 Person person = new Person("kuangshen",23); System.out.println(person.name); System.out.println(person.age); } } 构造器: 1.和类名相同 2.没有返回值 作用: 1.new的本质在调用方法 2.初始化对象的值 注意点: 1.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造 */
3、对象的创建分析
package oop.Demo03;
public class Pet {
public String name;
public int age;
//无参构造
public void shout(){
System.out.println("叫了一声");
}
}
package oop.Demo03;
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name="旺财";
dog.age=3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat = new Pet();
}
}
小结
1.类与对象
类是一个模板:抽象
对象是一个具体的实例
2.方法
定义、调用!
3.对象的使用
引用类型:基本类型(8)除了基本类型都是引用类型
对象是通过引用来操作的:栈-->堆
4.属性:字段Field 成员变量
默认初始化:
数字:0 0.0
char:u0000
boolean: false
引用:null
修饰符 属性类型 属性名 = 属性值!
5.对象的创建和使用
- 必须使用new关键字创造对象,构造器 Person kuangshen = new Person()
- 对象的属性 kuangshen.name
- 对象的方法 kuangshen.sleep()
6.类:
静态的属性 属性
动态的行为 方法
4、面向对象三大特性
封装
-
该露的露,该藏的藏
- 我们程序设计要追求==“高内聚,低耦合”。==高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
-
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
-
记住这句话就够了:属性私有,get/set。
package oop.Demo04; //类 private:私有 public class Student { //属性私有 private String name;//名字 private int id;//学号 private char sex;//性别 private int age;//年龄 //提供一些可以操作这个属性的方法 //提供一些public的get、set方法 //get 获得这个数据 public String getName(){ return this.name; } //set 给这个数据设置值 public void setName(String name){ this.name=name; } //alt+insert 生成get、set方法快捷键 public int getId() { return id; } public void setId(int id) { this.id = id; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { if (age>120 || age<0){ //不合法 this.age=3; }else { this.age = age; } } }
package oop.Demo04; public class Application { public static void main(String[] args) { Student s1 = new Student(); s1.setName("秦疆"); System.out.println(s1.getName()); s1.setAge(999);//不合法 System.out.println(s1.getAge()); } } /* 封装的意义: 1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 4.系统可维护性增加了 */
继承
- 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
- extends的意思是“扩展”,子类是父类的扩展。
- java中类==只有单继承,没有多继承==! 一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子。
- 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有以来、组合、聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
- 子类和父类之间,从意义上讲应该具有“is a”的关系。
- object类
- super - this
- 方法重写
- ctrl+h显示继承
package oop.Demo05;
//在java类中,所有的类,都默认直接或间接继承object
//person 人:父类
//当什么都不写的时候,就默认继承object类
public class Person /* extends object */{
//public
//protected 优先级大道与default
//default 默认
//private
public int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
package oop.Demo05;
//学生 is 人 :派生类。子类
//子类继承了父类,就会拥有父类的全部方法!
public class Student extends Person {
//ctrl+H 生成继承树快捷键
}
package oop.Demo05;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
System.out.println(student.money);
Person person = new Person();
}
}
super详解
package oop.Demo06;
public class Person {
public Person(String name) {
System.out.println("Person无参执行了");
}
protected String name = "kuangshen";
//私有的东西无法被继承!
public void print(){
System.out.println("Person");
}
}
package oop.Demo06;
public class Student extends Person{
public Student() {
//隐藏代码:调用了父类的无参构造
super("name");//调用了父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参执行了");
}
private String name = "qinjiang";
public void print(){
System.out.println("Student");
}
public void test(String name){
System.out.println(name);//秦疆
System.out.println(this.name);//qinjiang
System.out.println(super.name);//kuangshen
}
public void text1(){
print();//Student
this.print();//Student
super.print();//Person
}
}
package oop.Demo06;
public class Application {
public static void main(String[] args) {
Student student = new Student();
//student.test("秦疆");
//student.text1();
}
}
super - this注意点
super注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中!
3.super和this不能同时调用构造方法!
Vs this:
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承条件才可以使用
构造方法:
this():本类的构造
super():父类的构造!
重写
package oop.Demo07;
//重写都是方法的重写,和属性无关
public class B {
public void text(){
System.out.println("B=>text");
}
}
package oop.Demo07;
//继承
public class A extends B{
//Override 重写
@Override //注解:有功能的注释!
public void text() {
System.out.println("A=>text");
}
}
package oop.Demo07;
public class Application {
//静态的方法和非静态的方法区别很大!
//静态方法: 方法的调用只能和左边定义的数据类型有关
//非静态:重写
public static void main(String[] args) {
A a = new A();
a.text();//A
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.text();//B
}
}
重写注意点
重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大但不能缩小: public>Protected>Default>private
4.抛出的异常:范围,可以被缩小,但不能被扩大: ClassNotFoundException-->Exception(大)
重写,子类的方法和父类必须一致:方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要,或者不一定满足!
Alt+insert : override;
多态
- 动态编译类型:可扩展性。
- 及同一方法可以根据发送对象的不同而采用不同的行为方式。
- 一个对象的实际类型是确定的,但可以指定对象的引用类型有很多。
- 多态存在的条件
- 有继承关系
- 子类重写父类的关系
- 父类引用指向子类对象
- 注意:多态是方法的多态,属性没有多态性
- instanceof 类型转换~引用类型(强转,自转) 判断一个对象是什么类型。
package oop.Demo08;
public class Person {
public void run(){
System.out.println("father");
}
}
package oop.Demo08;
public class Student extends Person {
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
package oop.Demo08;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
Person s2 = new Student();
Object s3 = new Student();
//Person 父类形,可以指向子类,但是不能调用子类独有的方法
//对象能执行哪些方法,主要看对象做左边的类型,和右边的关系不大
s1.run();
s2.run();
s1.eat();
// s2.eat(); 子类重写了父类的方法,执行子类的方法
((Student) s2).eat(); //强制转换
}
}
多态注意点
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系 类型转换异常!ClassCastException!
3.存在条件:继承关系,方法需要重写,父类引用指向子类对象!
1.static 方法,属于类,它不属于实例;
2.final 常量;
3.private 方法;
instance和类型转换
package oop.Demo09;
public class Person {
public void run(){
System.out.println("run");
}
}
package oop.Demo09;
public class Student extends Person {
public void go(){
System.out.println("go");
}
}
package oop.Demo09;
public class Teacher extends Person {
}
package oop.Demo09;
public class Application {
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(student instanceof String);
//System.out.println(X instanceof Y);//能不能编译通过! 有没有父子关系。
}
}
package oop.Demo09;
public class Application02 {
public static void main(String[] args) {
//类型之间的转换:父 子
//高 低
Person obj = new Student();
//student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
Student student = (Student)obj;
student.go();
((Student)obj).go();
//子类转换为父类,可能丢失自己本来的一些方法!
Student student1 = new Student();
student.go();
Person person=student;
// person.go();
}
}
/*
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型
3.把父类转换为子类,向下转型:强制转换
4.方便方法的调用,减少重复的代码!简洁
封装、继承、多态! 抽象类,接口
*/
static 详解
package oop.Demo10;
//static
public class Student {
private static int age;//静态的变量 多线程!
private double score;//非静态的变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
System.out.println(s1.age);
System.out.println(s1.score);
go();
//run(); //非静态需要new一个才能用
}
}
package oop.Demo10;
//当Person加上final,就不能被继承!!!!
//但如果子类加上了final,却不影响它继承
public class Person {
//2:赋初始值~
{
System.out.println("匿名代码块");
}
//1:只执行一次~
static{
System.out.println("静态代码块");
}
//3
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("==============================");
Person person2 = new Person();
}
}
package oop.Demo10;
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Text {
public static void main(String[] args) {
System.out.println(random());//静态导入包后不用写 Math.random()
System.out.println(PI);
}
}
5、抽象类和接口
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么就是抽象类.
- 抽象类中可以没有抽象方法,但是抽象方法的类一定要声明为抽象类.
- 抽象类,不能使用new关键字来出创建对象,它是用来让子类继承的.
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的.
- 子类继承抽象类,那么就必须要实现抽象类没有实现的方法,否则该子类也要声明为抽象类.
package oop.Demo11;
//抽象类的所有方法,继承了他的子类,都必须要实现他的方法~ 除非子类也是抽象的
public class A extends Action {
@Override
public void doSomething() {
}
}
package oop.Demo11;
//abstract 抽象类:类 extends: 单继承 (接口可以实现多继承)
public abstract class Action {
//约束~有人帮我们实现~
//abstract,抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
//1.不能new这个抽象类,只能靠子类去实现它:约束!
//2.抽象类中可以写普通的方法~
//3.抽象方法必须在抽象类中~
//抽象的抽象:约束~
//思考题? new,存在构造器吗? 存在的意义? 抽象出来~ 提高开发效率
}
接口
-
普通类:只有具体实现。
-
抽象类:具体实现和规范(抽象方法)都有!
-
接口:只有规范!
-
接口就是和规范,定义的是一组规范,体现了现实生活中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
-
OOP的精髓,是对对象的抽象,最能体现着一点的接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如c++,java,c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
声明类的关键字是class。声明接口的关键字是interface。
package oop.Demo12;
//抽象类的思维~ Java
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//常量~ public static fianl
int AGE = 99;
//接口中的所有定义的方法其实都是抽象的 public adstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
package oop.Demo12;
public interface TimeService {
void timer();
}
package oop.Demo12;
//抽象类:extends~
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法~
//多继承~ 利用接口实现多继承~
public class UserServiceimpl implements UserService,TimeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
作用:
1.约束
2.定义一些方法,让不同的人实现~
3.方法:public abstract
4.常量:public static final
5.接口不能被实例化,接口中没有构造方法
6.implements可以实现多个接口
7.必须重写接口中的方法
6、内部类及OOP实战
- 内部类就是在一个类的内部再定义一个类,比如AA类中定义一个B类,那么B类相对于A类就称为内部类,而A类相对于B类就是外部类了
- 1.成员内部类
- 2.静态内部类
- 3.局部内部类
- 4.匿名内部类
package oop.Demo13;
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{ //若用static的话则不可以输出
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性~
public void getID(){
System.out.println(id);
}
}
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
//一个java类中可以有多个class类,但是只能有一个public class类。
class A{
public static void main(String[] args) {
}
}
package oop.Demo13;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
package oop.Demo13;
public class Test {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量中~
new Apple().eat();
UserService userService = new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}
7、异常处理详解
1.什么是异常
(1)概念:
◆实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了,等等。
◆软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
◆异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
◆异常发生在程序运行期间,它影响了正常的程序执行流程。
(2)简单分类:
◆检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
◆运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
◆错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。
2、异常体系结构
◆Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
◆在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
(1)、Error:
a. Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
b. Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
c. 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
(2)、Exception:
a.在Exception分支中有一个重要的子类RuntimeException(运行时异常)
*ArraylndexOutOfBoundsException(数组下标越界)
*NullPointerException(空指针异常)
*ArithmeticException(算术异常)
*MissingResourceException(丢失资源)
*ClassNotFoundException(找不到类)等异常,
这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
b.这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
c.Error和Exception的区别:
Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;
Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。
3.Java异常处理机制
● 捕获异常
● 抛出异常
● 异常处理的五个关键字:
try、catch、finally、throw、throws
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
try { //监控区域
System.out.println(a / b);
}catch (ArithmeticException e){//catch(异常类型),捕获异常
System.out.println("程序出现异常,变量不能为0");
}finally { //处理善后
System.out.println("finally");
}
}
}
多个异常:
package com.exception.demo;
/**
* @author Deng Huawei
* @create 2021-03-17 8:50
*/
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
//假设要捕获多个异常:从小到大
try { //监控区域
System.out.println(a / b);
}catch (Error e){ //catch,捕获异常
System.out.println("Error");
}catch (Exception e){
System.out.println("Exception");
}catch (Throwable e){
System.out.println("Throwable");
} finally { //处理善后
System.out.println("finally");
}
//finally 可以不用finally 假设I/O,资源关闭
}
}
自动生成:
主动抛出:
public class Test2 {
public static void main(String[] args) {
new Test2().div(1,0);
}
public void div(int a,int b){
if(b == 0){ //主动抛出异常 throw throws 一般在方法里用
throw new ArithmeticException();
}
System.out.println(a / b);
}
}
方法抛出
public class Test2 {
public static void main(String[] args) {
try {
new Test2().div(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
}
}
//假设这个方法中处理不了这个异常,方法上抛出异常
public void div(int a,int b) throws ArithmeticException{
if(b == 0){ //主动抛出异常 throw throws 一般在方法里用
throw new ArithmeticException();
}
System.out.println(a / b);
}
}
4.自定义异常
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
在程序中使用自定义异常类,大体可分为以下几个步骤:
(1) 创建自定义异常类。
(2) 在方法中通过throw关键字抛出异常对象。
(3) 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
(4) 在出现异常方法的调用者中捕获并处理异常。
例子:
//自定义异常类,继承Exception
package com.exception.demo.exceptiondemo;
/**
* @author Deng Huawei
* @create 2021-03-17 10:27
*/
//自定义异常类
public class MyException extends Exception {
//传递数字,>10抛出异常
private int detail;
public MyException(int a) {
this.detail = a;
}
//异常的打印信息
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
测试异常(在方法中进行抛出):
//在方法中抛出,运行时捕获
package com.exception.demo.exceptiondemo;
/**
* @author Deng Huawei
* @create 2021-03-17 10:39
*/
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if(a>10){
throw new MyException(a);
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException:"+e);
}
}
}
5.总结
◆ 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch处理
◆ 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
◆ 对于不确定的代码,也可以加上try-catch,处理潜在的异常
◆ 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
◆ 具体如何处理异常,要根据不同的业务需求和异常类型去决定
◆ 尽量添加finally语句块去释放占用的资源
Deng Huawei
- @create 2021-03-17 8:50
*/
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
//假设要捕获多个异常:从小到大
try { //监控区域
System.out.println(a / b);
}catch (Error e){ //catch,捕获异常
System.out.println("Error");
}catch (Exception e){
System.out.println("Exception");
}catch (Throwable e){
System.out.println("Throwable");
} finally { //处理善后
System.out.println("finally");
}
//finally 可以不用finally 假设I/O,资源关闭
}
}
#### **自动生成:**
[外链图片转存中...(img-dInQLEbO-1644305038017)]
#### **主动抛出:**
~~~java
public class Test2 {
public static void main(String[] args) {
new Test2().div(1,0);
}
public void div(int a,int b){
if(b == 0){ //主动抛出异常 throw throws 一般在方法里用
throw new ArithmeticException();
}
System.out.println(a / b);
}
}
方法抛出
public class Test2 {
public static void main(String[] args) {
try {
new Test2().div(1,0);
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
}
}
//假设这个方法中处理不了这个异常,方法上抛出异常
public void div(int a,int b) throws ArithmeticException{
if(b == 0){ //主动抛出异常 throw throws 一般在方法里用
throw new ArithmeticException();
}
System.out.println(a / b);
}
}
4.自定义异常
使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常类,只需继承Exception类即可。
在程序中使用自定义异常类,大体可分为以下几个步骤:
(1) 创建自定义异常类。
(2) 在方法中通过throw关键字抛出异常对象。
(3) 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
(4) 在出现异常方法的调用者中捕获并处理异常。
例子:
//自定义异常类,继承Exception
package com.exception.demo.exceptiondemo;
/**
* @author Deng Huawei
* @create 2021-03-17 10:27
*/
//自定义异常类
public class MyException extends Exception {
//传递数字,>10抛出异常
private int detail;
public MyException(int a) {
this.detail = a;
}
//异常的打印信息
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
测试异常(在方法中进行抛出):
//在方法中抛出,运行时捕获
package com.exception.demo.exceptiondemo;
/**
* @author Deng Huawei
* @create 2021-03-17 10:39
*/
public class Test {
//可能会存在异常的方法
static void test(int a) throws MyException {
System.out.println("传递的参数为:"+a);
if(a>10){
throw new MyException(a);
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException:"+e);
}
}
}
5.总结
◆ 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch处理
◆ 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
◆ 对于不确定的代码,也可以加上try-catch,处理潜在的异常
◆ 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
◆ 具体如何处理异常,要根据不同的业务需求和异常类型去决定
◆ 尽量添加finally语句块去释放占用的资源