毕向东Java笔记(全部)
目录
- 第一章 Java概述
- 基础常识
- 软件开发
- 人机交互
- 命令行方式
- 计算机语言
- 什么是计算机语言?
- Java语言概述
- Java语言的三种技术架构
- Java语言的特点:跨平台性
- Java语言的环境搭建
- 什么是JRE,JDK?
- 配置环境变量
- 第二章 Java基础语法
- 关键字
- 标识符
- 注释
- 常量与变量
- 运算符
- 算术运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 位运算符
- 练习
- 十六进制形式
- 三元运算符
- 流程控制
- 判断结构
- 选择结构
- 语句练习if-switch
- 循环结构
- while
- for
- 练习题
- 其他流程控制语句
- 函数
- 函数的定义
- 函数的特点
- 函数的应用
- 函数的重载(overload)
- 数组
- 数组的定义
- 内存结构
- 数组操作常见问题
- 数组常见操作
- 练习进制转换
- 二维数组
- 第三章 面向对象
- 面向对象概念
- 理解面向对象
- 面向对象的特点
- 面向对象开发,设计,特征
- 类与对象的关系
- 类与对象(图例)
- 类的定义
- 成员变量和局部变量的区别?
- 创建对象,使用对象
- 对象内存结构
- 匿名对象
- 封装(Encapsulation)
- private(私有)关键字
- 构造函数
- this关键字
- static(静态)关键字
- 单例设计模式
第一章 Java概述
基础常识
软件开发
- 什么是软件?
- 软件:一系列按照特定顺序组织的计算机数据和指令的集合。
- 常见的软件:
- 系统软件:
- 如DOS、windows、Linux等。
- 应用软件:
- QQ、迅雷等。
- 系统软件:
- 什么是开发?
- 制作软件
人机交互
- 软件的出现实现了人与计算机之间的更好交互。
- 交互方式:
- 图形化界面:这种方式简单直观,使用者已于接收,容易上手操作。
- 命令行方式:需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记录住一些命令。
命令行方式
在DOS里新建文件
copy con Demo.java
class Demo{public static void main(String[] args){System.out.println("Hello Java");}
}
Ctrl+Z 保存
type Demo.java
编译运行:
javac Demo.java
java Demodir 列出当前目录下的文件以及文件夹
md 创建目录
rd 删除目录
cd 进入指定目录
cd.. 退回到上一级目录
cd/ 退回到根目录
del 删除文件
exit 退出dos命令行
计算机语言
什么是计算机语言?
- 语言:是人与人之间用于沟通的一种方式。
例如:中国人与中国人用中文沟通。
而中国人要和韩国人交流,就要学习韩语。 - 计算机语言:人与计算机交流的方式。
如果人要与计算机交流,那么就要学习计算机语。
计算机语言有很多种,如:C,C++,Java等。
这里,我们选择其中的一种:Java语言。 - Java语言主要应用在互联网程序的开发领域。常见的互联网程序比如天猫、京东、物流系统、网银系统等,以及服 务器后台处理大数据的存储、查询、数据挖掘等也有很多应用。
Java语言概述
- 是SUN(Stanford University Network, 斯坦福大学网络公司)1995年推出的一门高级编程语言。
- 是一种面向Internet的编程语言。
- 随着Java技术在web方面的不断成熟,已经成为web应用程序的首选开发语言。
- 是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Java语言的三种技术架构
J2EE(Java 2 Platform Enterise Edition)企业版 |
---|
是为了开发企业环境下的引用程序提供的一套解决方案。该技术体系中包含的技术如Servlet Jsp等,主要针对于web应用程序开发 |
J2SE(Java 2 Platform Standard Edition)标准版 |
---|
是为开发普通桌面和商务应用程序提供的解决方案。 |
该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发。
J2ME(Java 2 Platform Micro Edition)小型版 |
---|
是为开发电子消费产品和嵌入式设备提供的解决方案。 |
该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。 |
Java5.0版本后,更名为JAVAEE JAVASE JAVAME
Java语言的特点:跨平台性
- 什么是跨平台性?
通过Java语言编写的应用程序在不同的系统平台上都可以运行。 - 原理是什么?
只要在需要运行Java应用程序的操作系统上,先安装一个Java虚拟机(JVM JAVA Virtual Machine)即可。
由JVM来负责Java程序在该系统中的运行。
因为有了JVM,所以同一个Java程序在三个不同的操作系统中都可以执行。这样就实现了Java程序的跨平台性。也称为Java具有良好的可移植性。
Java语言的环境搭建
什么是JRE,JDK?
JRE(Java Runtime Environment Java运行环境) |
---|
包括Java虚拟机(JVM Java Virtual Machine)和Java所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。 |
JDK(Java Development Kit Java开发工具包) |
- |
JDK是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就不用在单独安装JRE了。其中的开发工具:编译工具(javac.exe) 打包工具(jar.exe)等 |
简单而言:使用JDK开发完成的Java程序,交给JRE区运行。
配置环境变量
- 每次执行java的工具都要进入到bin目录下,是非常麻烦的。
- 可不可以在任何目录下都可以执行java的工具呢?
- 根据windows系统在查找可执行程序的原理,可以将java工具所在路径定义到path环境变量中,让系统帮我们去找运行执行的程序。
临时环境变量
set path=C:\Program Files\Java\jdk1.8.0_181\bin;%path%
随意目录下运行Java
set classpath=E:\test
java HelloWorldJava_HOME环境变量的配置
我的电脑右击属性-选择高级系统设置-环境变量-新建变量名JAVA_HOME,
变量值输入JDK的安装目录C:\Program Files\Java\jdk1.8.0_181
选中path环境变量编辑-输入%JAVA_HOME%\bin;移到最前面。
环境变量配置完成,重启DOS命令行,输入javac命令
第二章 Java基础语法
关键字
关键字的定义和特点:
定义:被Java语言赋予了特殊含义的单词
特点:关键字中所有字母都为小写
用于定义数据类型的关键字
class | interface | byte | short | int | long | float | double | char | boolean | void |
---|
用于定义数据类型的关键字
true | false | null |
---|
用于定义流程控制的关键字
if | else | switch | case | default | while | do | for | break | continue | return |
---|
用于定义访问权限修饰符的关键字
private | protected | public |
---|
用于定义类,函数,变量修饰符的关键字
abstract | final | static | synchronized |
---|
用于定义类与类之间关系的关键字
extends | implements |
---|
用于定义建立实例及引用实例,判断实例的关键字
new | this | super | instanceof |
---|
用于异常处理的关键字
try | catch | finally | throw | throws |
---|
用于包的关键字
package | import |
---|
其他修饰符关键字
native | strictfp | transient | volatile | assert |
---|
标识符
- 在程序中自定义的一些名称。
- 由26个英文字母大小写,数字:0~9 符号:_$组成
- 定义合法标识符规则:
- 数字不可以开头。
- 不可以使用关键字。
- Java中严格区分大小写。
- 注意:在起名字的时,为了提高阅读性,要尽量有意义。
Java中的名称规范: - 包名:多单词组成时所有字母都小写。
- xxxyyyzzz
- 类名接口名:多单词组成时,所有单词的首字母大写。
- XxxYyyZzz
- 变量名和函数名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写。
- xxxYyyZzz
- 常量名:所有字母都大写。多单词时每个单词用下划线连接。
- XXX_YYY_ZZZ
注释
- 用于注解说明解释程序的文字就是注释。
- 提高了代码的阅读性
- Java中的注释格式:
- 单行注释
- 格式:// 注释文字
- 多行注释
- 格式:/* 注释文字 */
- 文档注释
- /** 注释文字 */
- 单行注释
- 对于单行和多行注释,被注释的文字,不会被JVM(Java虚拟机)解释执行。
- 对于文档注释,是Java特有的注释,其中注释内容可以被JDK提供的工具javadoc所解析,生成一套以网页文件形式体现的该程序的说明文档。
- 注释是一个程序员必须要具有的良好变成习惯。
- 初学者编写程序可以养成习惯:先写注释再写代码
- 将自己的思想通过注释先整理出来,在用代码去体现。
- 因为代码仅仅是思想的一种体现形式而已。
/**
这是我的Hello World程序。
@author 冰冰
*/
class Demo{/*这是主函数,是程序的入口它的出现可以保证程序的独立运行*/public static void main(String[] args) {// 这是输出语句用于将括号内的数据打印到控制台。System.out.println("Hello World");}
}
常量与变量
- 常量表示不能改变的数值。
- Java中常量的分类:
- 整数常量。所有整数
- 小数常量。所有小数
- 布尔型常量。较为特有,只有两个数值。true false
- 字符常量。将一个数字字母或者符号用单引号(’’)标识。
- 字符串常量。将一个或者多个字符用双引号标识。
- null常量。只有一个数值就是:null。
- 对于整数:Java有三种表现形式。
- 十进制:0~9,满0进1
- 八进制:0~7,满8进1,用0开头表示
- 十六进制:0-9,A-F,满16进1.用0x开头表示
- 进制的基本转换
- 十进制 二进制 互转
- 十进制转成二进制 除以2取余数
- 二进制转成十进制 乘以2的幂数
- 十进制 八进制 互转
- 十进制 十六进制 互转
- 负数的二进制表现形式
- 对应的整数二进制取反加1
- 十进制 二进制 互转
十进制-->二进制 6的二进制
原理:对十进制数进行除2运算
6/2--0 3/2--1 1/2--1 110
二进制-->十进制 110的十进制
原理:二进制乘以2的过程。
0*2(0) + 1*2(1) + 1*2(2) = 0 + 2 + 4 = 6
128 64 32 16 8 4 2 1 5 + 4 = 9
----------------
101 + 100 = 1001 --> 9
转成16进制。四个二进制位就是一个十六进制位。0101-1010---------5 A --> 0x5A
转成8进制。三个二进制位代表一位
001-011-010 = 132
-----------1 3 2
负数的二进制表现形式。
6 = 110
-6 其实就是6的二进制取反+1
取反:将二进制的1变成0,0变成1
0000-0000 0000-0000 0000-0000 0000-0110 1111-1111 1111-1111 1111-1111 1111-1001
+0000-0000 0000-0000 0000-0000 0000-0001
----------------------------------------1111-1111 1111-1111 1111-1111 1111-1010 = -6
负数的最高位都是1.
- 变量的概念:
- 内存中的一个存储区域
- 该区域有自己的名称(变量名)和类型(数据类型)
- 该区域的数据可以在同一类型范围内不断变化
- 为什么要定义变量:
- 用来不断的存放同一类型的常量,并可以重复使用
- 使用变量注意:
- 变量的作用范围(一对{}之间有效)
- 初始化值
- 定义变量的格式:
- 数据类型 变量名 = 初始化值;
- 格式是固定的,记住格式,以不变应万变。
- 变量就如同数学中的未知数。
Java语言是强类型语言,对于每一种数据都要定义了明确的具体数据类型,在内存总分配了不同大小的内存空间
数据类型:基本数据类型、引用数据类型
基本数据类型:
数值型:整数类型(byte/short/int/long)、浮点类型(float/double)),字符型(char),布尔型(boolean)
引用数据类型:类(class)、接口(interface)、数组([])
整数默认int,小数默认double
- 自动类型转换(也叫隐式类型转换)
- 强制类型转换(也叫显式类型转换)
- 类型转换的原理
- 什么时候要用强制类型转换?
- 表达式的数据类型自动提升
- 所有的byte型、short型和char的值将被提升到int型。
- 如果一个操作数是long型,计算结果就是long型。
- 如果一个操作数是float型,计算结果就是float型。
- 如果一个操作数是double型,计算结果就是double型。
- 分析
- System.out.println(‘a’)与System.out.println(‘a’+1);的区别
a在ASCII码对应值是97
char和int相加,char会被强制转换int 97+1=98 - 自动类型提升
byte b = 3;
int x = 4;
x = x + b; // b会自动提升为int类型进行运算。
- 强制类型转换
byte b = 3;
b = b + 4; // 报错
b = (byte)b + 4; // 强制类型转换,强制将b+4的结果转换位byte类型,再赋值给b。
- 思考:
byte b1 = 3,b2 = 4,b;
b = b1 + b2;
b = 3 + 4;
哪句是编译失败的呢?为什么呢?
b = b1 + b2; //报错,因为java虚拟机在运算时会自动将b1和b2转换成int类型相加,所得的值是一个int类型的值,所以需要强转
b = 3 + 4;// byte类型的取值范围是-128到127,两个值相加编译器能够知道结果是多少,直接赋值没有问题,如果换成b=b1+4,就会报错,因为编译器不知道b1的值,他只知道b1是一个byte类型的变量,一个byte变量和一个int类型相加,会自动转换成int类型
数据类型 变量名 = 初始化值;
int x = 4;
System.out.println(x); // 4
x = 10;
System.out.println(x); // 10byte b = 2; // -128~127
// byte b1 = 128;
short s = 30000;
long l = 4L;
float f = 2.3F;
double d = 24.56;
char ch3 = ' ';boolean bo = true;
boolean bo1 = false;int a = 5;
a = a + 6;
System.out.println('a'); // a
System.out.println('a' + 1) // 98
// 所有的byte、short、char的值将被提升到int型。
byte b = 3;
// b = b + 2;
b = (byte)(b + 2);
System.out.println(b); // 5double d = 3.14;
int i = (int) d;
System.out.println(i); // 3System.out.println((char)97); // abyte b = 3;
b = 3 + 4;
// b = b + 4;byte b1 = 3, b2 = 4, b;
// b = b1 + b2;
b = (byte) (b1 + b2);
b = 3 + 4;
\n 回车换行
\b 退格
\r 回车
\t tab
运算符
算术运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 负号 | b=4,-b; | -4 |
+加 | 5+5 | 10 | |
- | 减 | 6-4 | 2 |
* | 乘 | 3*4 | 12 |
/ | 除 | 5/5 | 1 |
% | 取模 | 5%5 | 1 |
++ | 自增(前) | a=2;b=++a; | a=3,b=3 |
++ | 自增(后) | a=2;b=a++; | a=3,b=2 |
– | 自减(前) | a=2;b=–a; | a=1;b=1 |
– | 自减(后) | a=2;b=a– | a=1;b=2 |
+ | 字符串相加 | “he”+“llo” | “hello” |
- 算术运算符的注意问题
- 如果对负数取模,可以把模数负号忽略不记,如:5%-2=1。但被模数的负数就另当别论
- 对于除号"/",它的整数除和小数除是有去别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
- 例如:int x = 3510;x=x/1000*1000; x的结果是?3000
- "+"除字符串相加功能外,还能把非字符串转换成字符串
- 例如:System.out.println(“5+5=”+5+5); // 打印结果是?5+5=55
int x = 4270;
x = x / 1000 * 1000;
System.out.println(x); // 4000System.out.println(-1%5); // -1
int a = 3,b;
a++; // a = a + 1;
b = ++a;
System.out.println("a = " + a + "b = " + b); // a = 5,b = 5
System.out.println("5+5="+(5+5)); // 5+5=10
赋值运算符
- 符号:
=,+=,-=,*=,/=,%= - 示例:
int a,b,c;
a=b=c=3;
int a=3;
a+=5; //等同运算a=a+5;
- 思考:
short s = 3;
// 2是int类型的常量 s+2会自动转换成int型,int型赋给一个short型的s自然会出错
s = s + 2; // 报错 改为(short)(s+2)
s += 2;
有什么区别?
编译器自动将+=运算符后面的操作数强制转换为前面变量的类型
同时类似的还有: -= *= /= %=
int x = 3;
// += -= *= /= %=
short s = 4;
// s = (short) (s + 5);
s += 5;
System.out.println(s);int a,b,c;
a = b = c = 5;
比较运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | false |
!= | 不等于 | 4!=3 | true |
< | 小于 | 4<3 | false |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | false |
instanceof | 检查是否类的对象 | “Hello” instance String | true |
- 比较运算符的结果都是boolean型,也就是要么是true,要么是false。
- 比较运算符"==“不能误写成”="。
逻辑运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
& | AND(与) | false&true | false |
|
|
OR(或) |
false| true
|
true |
^ | XOR(异或) | true^false | true |
! | Not(非) | !true | false |
&& | AND(短路) | !true | false |
||
|
OR(短路) |
false|| true
|
true |
- 逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3&x<6。
- "&“和”&&"的区别:
- &时,左边无论真假,右边都进行运算
- &&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
"|“和”||"的区别同理,爽或时,左边为真,右边不参与运算。
- 异或(^)与或(|)的不同之处是:当左右都为true时,结果为false。
int x = 7;
x > 3 & x < 6; // true & false = false
true & true = true;
true & false = false;
false & true = false;
false & false = false;
&(与) 只要两边的boolean表达式结果,有一个为false。那么结果就是false。
true & true = true;
true & false = true;
false & true = true;
false & false = false;
|(或) 两边只要有一个为true,结果为true。只有两边都有false,结果为false。
true ^ true = false;
true ^ false = true;
false ^ true = true;
false ^ false = false;
^(异或) 两边相同结果是false。
!(非) !true = false、 !false = true
int a = 2;
a>3 && a<6;
短路
&和&&的特点:
& 无论左边是true还是false,右边都运算。
&& 当左边为false时,右边不运算。
| 两边都参与运算
|| 当左边为true。右边不运算
位运算符
运算符 | 运算 | 范例 |
---|---|---|
<< | 左移 | 3<<2=12–>322=12 |
>> | 右移 | 3 >>1=1‐‐>3/2=1 |
>>> | 无符号右移 | 3 >>>1=1‐‐>3/2=1 |
& | 与运算 | 6&3==2 |
|
|
或运算 |
6| 3=7
|
^ | 异或运算 | 6^3=5 |
~ | 反码 | ~6=-7 |
位运算是直接对二进制进行运算。
位运算符的细节
位运算符的细节 | |
---|---|
<< | 空位补0,被移除的高位丢弃,空缺位补0 |
>> | 被移位的二进制最高位是0,右移后,空缺位补0;最高位是1,空缺位补1 |
>>> | 被移位二进制最高位无论是0或者是1,空缺位都用0补 |
& | 二进制位进行&运算,只有1&1时结果是1,否则是0; |
|
|
二进制位进行| 运算,只有0| 0时结果是0,否则是1;
|
^ | 任何相同二进制位进行 ^ 运算,结果是0;1 ^ 1 = 0, 0 ^ 0 = 0 不相同二进制位 ^ 运算结果是1。1 ^ 0=10 ^ 1=1 |
3 << 2 = 12;(3*4=12) 3 << 1 = 6;(3*2=6) 3 << 3 = 24;(3*8=24)
0000-0000 0000-0000 0000-0000 0000-0011 3
<< 2
0000-0000 0000-0000 0000-0000 0000-1100 126 >> 2 = 1;(6/4=1) 6 >> 1 = 3;(6/2=3)
0000-0000 0000-0000 0000-0000 0000-0110 6
>> 2
0000-0000 0000-0000 0000-0000 0000-0001 13 << 2 --> 3*2的2次幂
<< 其实就是乘以2的移动的位数次幂
>> 就是除以2的移动的位数次幂1111-1111 1111-1111 1111-1111 1111-1010 = -6
>> 2
1111-1111 1111-1111 1111-1111 1111-1110
>>> 2
0011-1111 1111-1111 1111-1111 1111-1110
>> 最高位补什么由原有数据的最高位值而定。
如果最高位0,右移后,用0补空位。
如果最高位1,右移后,用1不空位。
>>> 无论最高位是什么,右移后,都用0补。&
6 & 3 = 2110
&011
-----010 = 2|
6 | 5 = 7110
|101
------111 = 7^
6 ^ 5 = 3110
^101
------011 = 3System.out.println(~6); // -7
0000...000110
1111...111001
0000...000001
1111...111000
0000...000111System.out.println(7 ^ 4);
7 ^ 4111
^100
-----011
^100
-----111 = 7 ^ 4 = 4 ^ 4 = 7一个数异或同一个数两次,结果还是那个数。
练习
1. 最有效率的方式算出2乘以8等于几? 2<<3
2. 对两个整数变量的值进行互换(不需要第三方变量)
int n = 3, m = 8;
System.out.println("n = " + n + ",m = " + m);
// 1. 通过第三方变量
int temp = n;
n = m;
m = temp;
// 2. 不用第三方变量
// 如果n和m的值非常大,容易超出int范围。
n = n + m; // 11 = 3 + 8
m = n - m; // 3 = 11 + 8
n = n - m; // 8 = 11 - 8n = n ^ m; //
m = n ^ m; // (n^m)^m
n = n ^ m; // n^(n^m)
System.out.println("n = " + n + ",m = " + m);
十六进制形式
0000-0000 0000-0000 0100-1100 1110-0110
----------------------------------------4 12 14 60000-0000 0000-0000 0100-1100 1110-0110
&0000-0000 0000-0000 0000-0000 0000-1111
-----------------------------------------0000-0000 0000-0000 0000-0000 0000-0110
===========================================0000-0000 0000-0000 0000-0000 0011-1100 = 60
60&15 = 12
0000-0000 0000-0000 0000-0000 0011-1100
0000-0000 0000-0000 0000-0000 0000-1111
-----------------------------------------
0000-0000 0000-0000 0000-0000 0000-1100 = 12temp = 60>>>4
temp & 15 = 3
0000-0000 0000-0000 0000-0000 0000-0011 1100
0000-0000 0000-0000 0000-0000 0000-1111
----------------------------------------
0000-0000 0000-0000 0000-0000 0000-0011 = 3
三元运算符
格式:(条件表达式)?表达式1:表达式2;
- 如果条件为true,运算后的结果是表达式1;
- 如果条件为false,运算后的结果是表达式2;
System.out.println(Integer.toBinaryString(60)); // 二进制 111100System.out.println(Integer.toHexString(60)); // 十六进制 3cSystem.out.println(Integer.toOctalString(60)); // 八进制 74int num = 60;// 获取60的最低4位,通过&15int n1 = num & 15;System.out.print(n1 > 9 ? (char) (n1 - 10 + 'a') : n1 + ""); // c// 要获取下一组四位,将60右移4位int temp = num >>> 4;// 对temp的值进行最低四位的获取。int n2 = temp & 15;System.out.print(n2 > 9 ? (char) (n2 - 10 + 'a') : n2); // 3System.out.println();/*0-9 'a' 'b' 'c' 'd' 'e' 'f'97 98 9910 11 12 13 14 1512 - 10 = 2 + 'a' = (char)99;*/int x = 1, y;y = (x > 1) ? 100 : 200;System.out.println("y = " + y);
获取两个数中大数。
int x = 3, y = 4,z;
z = (x > 1) ? x: y;
System.out.println("z = " + z);
流程控制
判断结构
格式:
if(条件表达式){// 执行语句;}else if(条件表达式){// 执行语句;}else {// 执行语句;}
特点:
条件表达式无论写成什么样子,只看最终的结果是否是true或者false
int x = 1;if(x>1) {System.out.println("yes"):}else {System.out.println("a");}
/*if else结果简写格式:变量 = (条件表达式)?表达式1:表达式2;三元运算符:好处:可以简化if else代码弊端:因为是一个运算符,所以运算完必须要有一个结果。
*/int a = 9,b;b = (a>1)?100:200;if(a>1)b = 100;elseb = 200;int n = 3;if(n > 1)System.out.println("a");else if(n > 2)System.out.println("b");else if(n > 3)System.out.println("c");else System.out.println("d"):
/*if(n>1)System.out.println("a");if(n>2)System.out.println("b");if(n>3)System.out.println("c");elseSystem.out.println("d");System.out.println("over");
*/// 需求1:根据用户定义的数值不同。打印对应的星期英文。int num = 1;if(num == 1) {System.out.println("Monday");}else if(num == 2) {System.out.println("Tuesday");}else {System.out.println("no");}// 需求2:根据用于指定月份,打印该月份所属的季节。int x = 4;if(x>12 || x<1) {System.out.println(x + "月份不存在");}else if(x>=3 && x<=5) {System.out.println(x + "春季");}else if(x>=6 && x<=8) {System.out.println(x + "夏季");}else if(x>=9 && x<=11) {System.out.println(x + "秋季");}else {System.out.println(x + "冬季");}
/*
已知学生成绩以100分为满分,共分5个等级:A,B,C,D,E。
90~100为等级A,80~89为等级B,70~79为等级C,
60~69为等级D,0~59为等级E。
要求定义一个成绩变量,当成绩变化时,可直接知道该成绩对应的等级。
例如:当成绩为100时,该学生的等级时A。
*///定义一功能,通过给定分数,获取该分数对应的等级。/*1,明确该功能的结果:等级 char2,有没有未知内容。分数。int*/public static String getLevel(int num) {char level; // 等级if(num>=90 && num<=100)level = 'A';else if(num>=80 && num<=89)level = 'B';else if(num>=70 && num<=79)level = 'C';else if(num>=60 && num<=69)level = 'D';elselevel = 'E';return level;}public static void main(String[] args) {char ch = getLevel(35);System.out.println("level="+ch);}
选择结构
格式:
switch(表达式) {case 取值1:执行语句;break;case 取值2:执行语句;break;...default:执行语句;break;}
- switch语句选择的类型只有四种:byte、short、int、char。
- case之间与default没有顺序。先执行第一个case,没有匹配的case执行default。
- 结果switch语句的两种情况:遇到break,执行到switch语句结束。
- 如果匹配的case或者default没有对应的break,那么程序会继续向下执行,运行可以执行的语句,直到遇到break或者switch结尾结束。
习题
int x = 3;// byte short int charswitch(x) {default:System.out.println("d")://break;case 4:System.out.println("a");//break;case 6:System.out.println("b");break;case 2:System.out.println("c");break;}// 输出:d a b
int a = 4,b = 2;char ch = '+';switch(ch) {case '-':System.out.println(a-b);break;case '+':System.out.println(a+b); // 6break;case '*':System.out.println(a*b);break;case '/':System.out.println(a/b);break;default:System.out.println("非法");}
// 需求2:根据用于指定月份,打印该月份所属的季节。int x = 4;switch (x) {case 3:case 4:case 5:System.out.println(x + "春季"); // 春季break;case 6:case 7:case 8:System.out.println(x + "夏季");break;case 9:case 10:case 11:System.out.println(x + "秋季");break;case 12:case 1:case 2:System.out.println(x + "冬季");break;default:System.out.println("no");break;
}
if和switch语句很像。
具体什么场景下,应用哪个语句呢?
如果判断的具体数值不多,而是符合byte、short、int、char四种类型。
虽然两个语句都可以使用,建议使用switch语句,因为效率稍高。
其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。
语句练习if-switch
第一题
int x = 1, y = 1;
if (x++ == 2 & ++y == 2) {x = 7;
}
System.out.println("x=" + x + ",y=" + y); // x=2,y=2
第二题
int x = 1, y = 1;
if (x++ == 2 && ++y == 2) {x = 7;
}
System.out.println("x = " + x + ",y = " + y); // x = 2,y = 1
第三题
int x = 1, y = 1;
if (x++ == 1 | ++y == 1) {x = 7;
}
System.out.println("x = " + x + ",y = " + y); // x = 7,y = 2
第四题
int x = 1, y = 1;
if (x++ == 1 || ++y == 1) {x = 7;
}
System.out.println("x = " + x + ",y = " + y); // x = 7,y = 1
第五题
boolean b = true;if (b == false) // 如果写成if(b=false)有结果吗?如果有,结果是? cSystem.out.println("a");
else if (b)System.out.println("b"); // b
else if (!b)System.out.println("c");
elseSystem.out.println("d");
第六题
int x = 2,y = 3;
switch(x) {default:y++;case 3:y++;case 4:y++;
}
System.out.println("y = " + y); // 6
循环结构
while
语句格式:while(条件表达式) {执行语句;}int x = 1;while (x < 3) {System.out.println("x = " + x);x++;}int x = 1;do {System.out.println("do: x = " + x); // 1x++;} while (x < 0);int y = 1;while (y < 0) {System.out.println("y = " + y);y++;}
while:先判断条件,只有条件满足才执行循环体。
do while:先执行循环体,再判断条件,条件满足,再继续执行循环体。
do while:特点是无论条件是否满足,循环体至少执行一次
for
语句格式:for(初始化表达式;循环条件表达式;循环后的操作表达式) {执行语句;}
- for里面表达式运行的顺序,初始化表达式只读一次,判断循环条件,为真就执行循环体,然后再执行循环后的操作表达式,接着继续判断循环条件,重复找的过程,直到条件不满足为止。
- while与for可以互换,区别在于for为了循环而定义的变量在for循环结束就是在内存中释放。而while循环使用的变量在循环结束后还可以继续使用。
- 最简单无限循环格式:while(true),for( ; ; ),无限循环存在的原因是并不知道循环多少次,而是根据某些条件,来控制循环。
for (int x = 0; x < 3; x++) {System.out.println("x = " + x); // 0 1 2}// System.out.println("x = " + x);System.out.println("============");int y = 0;while (y < 3) {System.out.println("y = " + y); // 0 1 2y++;}System.out.println("y = " + y); // 3/*1. 变量有自己的作用域。对于for来讲: 如果将用于控制循环的增量定义在for语句中,那么变量只在for语句中那么该变量只在for语句内有效。for语句执行完毕。该变量在内存中被释放。 2. for和while可以进行互换。如果需要定义循环增量。用for更为合适。*/// 总结:什么时候使用循环结构? 当要对某些语句执行很多次时,就是用循环结构。
int x = 1;for (System.out.println("a"); x < 3;System.out.println("c"), x++) {System.out.println("d");}// adcdcfor (int y = 0; y < 3; y++) {}// 无限循环的最简单表现形式。for (;;) {}while(true) {}
练习题
// 1. 获取1~10的和,并打印。// 1. 定义变量用于存储不断变化的和。int sum = 0;// 2. 定义变量,记录住不断变化的被加的数。int x = 1;// 3. 定义循环,重复加法的过程。while (x <= 10) {sum = sum + x;x++;}System.out.println("sum=" + sum);/** 循环注意:一定要明确哪些语句需要参与循环,哪些不需要。*/0 + 11 + 23 + 36 + 4// 用for来实现。int sum = 0;for (int x = 0; x <= 10; x++) {sum += x;}System.out.println("for sum = " + sum);/** 其实这就是累加思想。* 原理:通过变量记录每次变化的结果。* 通过循环的形式。进行累加动作。* */
/*
2. 1~100之间 7的倍数的个数。并打印。
思路:
1. 先对1~100进行循环(遍历)通过循环的形式。
2. 在遍历的过程中,定义条件。只对7的倍数进行操作。
2. 因为7的倍数不确定,只要符合条件,就通过一个变量来记录住这个变化的次数。步骤:- 定义循环语句,选择for语句。- 在循环中定义判断。只要是7的倍数即可。使用if语句。条件:7的倍数 x%7==0;- 定义变量,该变量随着7的倍数的出现而自增。
*/int count = 0;for (int i = 1; i <= 100; i++) {if (i % 7 == 0) {System.out.println(i);count++;}}System.out.println("count = " + count);/** 计数器思想。 * 通过一个变量记录数据的状态变化。 * 也需要通过循环完成。*/
// 循环嵌套 其实就是语句中还有语句// ****// ****// ****for (int x = 0; x < 3; x++) {for (int y = 0; y < 4; y++) {System.out.print("*");}System.out.println(); // 只有一个功能就是换行。}// *****// ****// ***// **// *for (int x = 0; x < 5; x++) { // x<5因为外循环控制行数。一共5行for (int y = 5; y > x; y--) {System.out.print("*");}System.out.println();}// *// **// ***// ****// *****for (int x = 1; x <= 5; x++) {for (int y = 0; y < x; y++) {System.out.print("*");}System.out.println();}// 1// 12// 123// 1234// 12345for (int x = 1; x <= 5; x++) {for (int y = 1; y <= x; y++) {System.out.print(y);}System.out.println();}// 九九乘法表// 1*1=1// 1*2=2 2*2=4// 1*3=3 2*3=6 3*3=9for (int x = 1; x <= 9; x++) {for (int y = 1; y <= x; y++) {System.out.print(y + "*" + x + "=" + x * y + "\t");}System.out.println();}// ----*// ---* *// --* * *// -* * * *// * * * * *Scanner c = new Scanner(System.in);int i = c.nextInt();for (int x = 0; x < i; x++) {for (int y = x; y < i - 1; y++) {System.out.print(" ");}for (int z = 0; z <= x; z++) {System.out.print("* ");}System.out.println();}// * * * * *// -* * * *// --* * *// ---* *// ----*for (int x = 0; x < i; x++) {for (int y = 0; y < x; y++) {System.out.print(" ");}for (int z = i; z > x; z--) {System.out.print("* ");}System.out.println();}
其他流程控制语句
break(跳出) continue(继续)
break语句应用范围:选择结构和循环结构
continue语句:应用于循环结构
- 这两个语句离开应用范围,存在时没有意义的。
- 这两个语句单独存在下面都不可以有语句,因为执行不到
- continue语句结束本次循环继续下次循环。
- 标号的出现,可以让这两个语句作用于指定的范围。
w: for (int x = 0; x < 3; x++) {for (int y = 0; y < 4; y++) {System.out.println("x = " + x); // 0break w;}
}// continue 只能作用于循环结构。继续循环。特点:结束本次循环,继续下一次循环for (int x = 1; x <= 10; x++) {if (x % 2 == 1)continue;// System.out.println("x = " + x); // 2 4 6 8 10}w: for (int x = 0; x < 3; x++) {for (int y = 0; y < 4; y++) {System.out.println("x = " + x); // 0 1 2continue w;}}/** 记住:* 1. break和continue语句作用的范围。 * 2. break和continue单独存在时,下面不可以有任何语句。因为都执行不到。*/// break;// continue;
函数
函数的定义
- 什么是函数?
- 函数就是定义在类中的具有特定功能的一段独立小程序。
- 函数也称为方法。
- 函数的格式:
修饰符 返回值类型 函数名(参数类型 形式参数1, 参数类型 形式参数2, ...) {执行语句;return 返回值;
}
返回值类型:函数运行后的结果是数据类型。
参数类型:是形式参数的数据类型。形式参数:传递给参数的具体数值。
return:用于结束函数。
返回值:该值会返回给调用者。
public static void main(String[] args) {int x = 4;System.out.println(x * 3 + 5); // 17x = 6;System.out.println(x * 3 + 5); // 23// int y = 4*3+5;// int z = 6*3+5;int y = getResultInt(4);System.out.println("y=" + y); // y = 17int z = getResultInt(6);getResultVoid(5); // 20
}// 发现以上的运算,因为获取不同数据的运算结果,代码出现了重复。
// 为了提高代码的复用性。对代码进行抽取。
// 将这个部分定义成一个独立的功能。方便与日后使用。
// java中对功能的定义是通过函数的形式来体现的。// 需要定义功能,完成一个整数的*3+5的运算,// 1. 先明确函数定义的格式。
/** 修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,) { 执行语句; return 返回值; }* * 当函数运算后,没有具体的返回值时,这是返回值类型用一个特殊的关键字来标识。 该关键字就是void。void:代表的是函数没有具体返回值的情况。* 当函数的返回值类型是void时,函数中的return语句可以省略不写。*/
public static int getResultInt(int num) {return num * 3 + 5;
}public static void getResultVoid(int num) {System.out.println(num * 3 + 5);return;// 可以省略
}
函数的特点
- 定义函数可以将功能代码进行封装
- 函数只有被调用才会被执行
- 函数的出现提高了代码的复用性
- 对于函数没有具体返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写。
- 函数中只能调用函数,不可以在函数内部定义函数。
- 定义函数时,函数的结果应该返回给调用者,交给调用者处理。
函数的应用
- 两个明确
- 明确要定义的功能最后的结果是什么?
- 明确在定义该功能的过程中,是否需要未知内容参与运算
- 实例:
- 需求:定义一个功能,可以实现两个整数的加法运算。
- 分析:
- 该功能的运算结果是什么?两个数的和,也是一个整数(int)
- 在实现该功能的过程中是否有未知内容参与运算?加数和被加数是不确定的。(两个参数int,int)
- 代码
int getSun(int x,int y) {return x+y; }
public static void main(String[] args) {draw(5, 6);printHr();draw(7, 9);printHr();print99();}/** 定义一个打印99乘法表功能的函数。*/public static void print99() {for (int x = 1; x <= 9; x++) {for (int y = 1; y <= x; y++) {System.out.print(y + "*" + x + "=" + y * x + "\t");}System.out.println();}}/** 定义一个功能,用于打印矩形。 * 思路: * 1. 确定结果:没有,因为直接打印。所以返回值类型是void * 2. 有未知内容吗?有,两个,因为矩形的行和列不确定。*/public static void draw(int row, int col) {for (int x = 0; x < row; x++) {for (int y = 0; y < col; y++) {System.out.print("*");}System.out.println();}}public static void printHr() {System.out.println("------------------------------");}
函数的重载(overload)
重载的概念 |
---|
在同一个类中,允许存在一个以上的同名函数,只要它们 |
重载的特点: |
---|
与返回值类型无关,只看参数列表。 |
重载的好处: |
---|
方便于阅读,优化了程序设计。 |
重载示例:
// 返回两个整数的和
int add(int x,int y) {return x + y;
}
// 返回三个整数的和
int add(int x,int y,int z) {return x+y+z;
}
// 返回两个小数的和
double add(double x,double y) {return x+y;
}
/*
什么时候用重载?
当定义的功能相同,但参与运算的未知内容不同。
那么,这时就定义一个函数名称以表示起功能,方便阅读,而通过参数列表的不同来区分多个同名函数。
*/
public static void main(String[] args) {System.out.println(add(4, 5)); // 9System.out.println(add(4, 5, 6)); // 15print99();
}public static void print99(int num) {for (int x = 1; x <= num; x++) {for (int y = 1; y <= x; y++) {System.out.print(y + "*" + x + "=" + y * x + "\t");}System.out.println();}
}// 打印99乘法表
public static void print99() {print99(9);
}// 定义一个加法运算,获取两个整数的和。
public static int add(int x, int y) {return x + y;
}// 定义一个加法,获取三个整数的和。
public static int add(int x, int y, int z) {return add(x, y) + z;
}
数组
数组的定义
概念 |
---|
同一种类型数据的集合。其实数组就是一个容器。 |
数组的好处 |
---|
可以自动给数组中的元素从0开始编号,方便操作这些元素。 |
格式1: |
---|
元素类型[] 数组名 = new 元素类型[元素个数或数组长度]; |
示例:int[] arr = new int[5]; |
格式2: |
---|
元素类型[] 数组名 = new 元素类型[] {元素, 元素, …} |
int[] arr = new int[]{3, 5, 1, 7}; |
int[] arr = {3, 5, 1, 7}; |
//元素类型[] 数组名 = new 元素类型[元素个数或数组长度];//需求:想定义一个可以存储3个整数的容器。
int[] x = new int[3];//打印数组中角标为0的元素的值。
System.out.println(x[1]); // 0
public static void main(String[] args) {int sum = getSum(4, 6);System.out.println("sum=" + sum);sum = getSum(2, 7);System.out.println("sum=" + sum);get(4,5);int x = getSum(4, 4);int y = getSum(7, 9);int num = getMax(x, y);}/** 这个功能定义思想有问题,为什么呢? * 因为只为完成加法运算,至于是否要对和进行打印操作, 那是调用者的事,不要在该功能中完成。*/public static void get(int a, int b) {System.out.println(a + b);return;}/** 如何定义一个函数呢? * 1. 既然函数是一个独立的功能,那么该功能的运算结果是什么先明确 因为这是在明确函数的返回值类型。* 2. 在明确在定义该功能的过程中是否需要未知的内容参与运算。 因为是在明确函数的参数列表(参数的类型和参数的个数)。*/// 需求:定义一个功能。完成3+4的运算。并将结果返回给调用者。/** 1. 明确功能的结果:是一个整数的和。 * 2. 在实现该功能的过程中是否有未知内容参与运算,没有。 其实这两个功能就是在明确函数的定义。* 1. 是在明确函数的返回值类型。* 2. 明确函数的参数列表( 参数的类型和参数的个数)。*/public static int getSum() { return 3+4; }/** 以上这个函数的功能,结果是固定的,毫无扩展性而言。 * 为了方便用户需求。由用户来指定加数和被加数。这样,功能才有意义。 * 思路:* 1. 功能结果是一个和。返回值类型是int。 * 2. 有未知内容参与运算。有两个。这个两个未知内容的类型都是int。*/public static int getSum(int x, int y) {return x + y;}/** 需求:判断两个数是否相同。 * 思路:* 1. 明确功能的结果:结果是:boolean 。 * 2. 功能是否有未知内容参与运算。有,两个整数。*/public static boolean compare(int a, int b) {// if (a == b)// return true;// else// return false;// return (a==b) ? true : false;return a == b;}/** 需求:定义功能,对两个数进行比较。获取较大的数。*/public static int getMax(int a, int b) {// if (a > b) {// return a;// } else {// return b;// }return (a > b) ? a : b;}
内存结构
Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,有对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈内存 |
---|
用于存储局部变量,当数据使用完,所占空间会自动释放。 |
堆内存 |
---|
数组和对象,通过new建立的实例都存放在堆内存中。 |
每一个实体都有内存地址值 |
实体中的变量都有默认初始化值 |
实体中的变量都有默认初始化值 |
实体不在被使用,会在不确定的时间内被垃圾回收器回收 |
方法区 |
---|
存储可以运行的class文件。 |
本地方法区 |
---|
JVM在使用操作系统功的时候使用,和我们开发无关。 |
寄存器 |
---|
给CPU使用,和我们开发无关。 |
数组操作常见问题
数组下标越界异常(ArrayIndexOutOfBoundsException) |
---|
int[] arr = new int[2]; |
System.out.println(arr[3]): |
访问到了数组中的不存在的下标时发生。 |
空指针异常(NullPointerException) |
---|
int[] arr = null; |
System.out.println(arr[0]); |
arr引用没有指向实体,却在操作实体中的元素时。 |
int[] arr = new int[2];
int arr[] = new int[2];
int[] arr = new int[] { 3, 1, 6, 5, 4 };
int[] arr = {3,1,6,5,4};
System.out.println(arr[2]);
int[] arr = new int[5];
arr[0] = 90;
arr[1] = 80;int[] arr = new int[3];
System.out.println(arr[3]);
// ArrayIndexOutOfBoundsException: 操作数组时,访问到了数组中不存在的角标。arr = null;
System.out.println(arr[1]);
// NullPointerException:空指针异常:当引用没有任何指向值为null的情况,该引用还在用于操作实体。
public static void main(String[] args) {// 获取数组中的元素。通常会用到遍历。int[] arr = { 3, 6, 5, 1, 8, 9, 7, 2, 4, 10 };// 数组中有一个属性可以直接获取到数组元素个数。length// 使用方式:数组名称.lengthSystem.out.println(arr.length); // 10int sum = 0;for (int x = 0; x < arr.length; x++) {sum += arr[x];System.out.println("arr[" + x + "] = " + arr[x] + ";");}System.out.println(sum); // 55printArray(arr); // [3,6,5,1,8,9,7,2,4,10]System.out.println(arr); // [I@52e922
}// 定义功能,用于打印数组中的元素。元素间用逗号隔开。
public static void printArray(int[] arr) {System.out.print("[");for (int x = 0; x < arr.length; x++) {if (x != arr.length - 1) {System.out.print(arr[x] + ",");} else {System.out.print(arr[x] + "]");}}System.out.println();
}
数组常见操作
- 获取最值(最大值,最小值)
/** 获取数组中的最大值。 * 思路: * 1. 获取最值需要进行比较。每一次比较都会有一个较大的值。因为该值不确定。 通过一个变量进行临时存储。 * 2. 让数组中的每一个元素都和这个变量中的值进行比较。 如果大于了变量中的值,就用该该变量记录较大值。 * 3. 当所有的元素都比较完成,那么该变量中存储的就是数组中的最大值了。* * 步骤: * 1. 定义变量。初始化为数组中任意一个元素即可。 * 2. 通过循环语句对数组进行遍历。 * 3. 在变量过程中定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给该变量。* * 需要定义一个功能来完成。以便提高复用性。 * 1. 明确结果,数组中的最大元素 int。 * 2. 未知内容:一个数组。int[]*/public static int getMax(int[] arr) {int max = arr[0];for (int x = 1; x < arr.length; x++) {if (arr[x] > max) {max = arr[x];}}return max;}/** 获取最大值的另一种方式。 可不可以将临时变量初始化为0呢?可以。这种方式,其实在初始化为数组中任意一个下标。*/public static int getMax_2(int[] arr) {int max = 0;for (int x = 1; x < arr.length; x++) {if (arr[x] > arr[max])max = x;}return arr[max];}/** 获取最小值。*/public static int getMin(int[] arr) {int min = 0;for (int x = 1; x < arr.length; x++) {if (arr[x] < arr[min]) {min = x;}}return arr[min];}// 获取double类型数组的最大值。因为功能一致,所以定义相同函数名称。以重载形式存在。// public static double getMax(double[] arr) {//// }public static void main(String[] args) {int[] arr = { 3, 6, 5, 1, 8, 9, 7, 2, 4, 10 };int max = getMax(arr);System.out.println("max = " + max); // 10int min = getMin(arr);System.out.println("min = " + min); // 1boolean[] ar = new boolean[3];System.out.println(ar[1]); // false}
- 排序(选择排序,冒泡排序)
public static void main(String[] args) {int[] arr = { 3, 6, 5, 1, 8, 9, 7, 2, 4, 10 };// 排序前:printArray(arr);// 排序selectSort(arr);bubbleSort(arr);Arrays.sort(arr); // Java中已经定义好的一种排序方式。开发中,对数组排序。要使用该句代码。// 排序后:printArray(arr);// 反转后:reverseArray(arr);printArray(arr);
}
/** 选择排序。 内循环结束一次,最值出现头角标位置上。*/
public static void selectSort(int[] arr) {// 没有必要遍历最后一个角标for (int x = 0; x < arr.length - 1; x++) {for (int y = x + 1; y < arr.length; y++) {if (arr[x] > arr[y]) {// int temp = arr[x];// arr[x] = arr[y];// arr[y] = temp;swap(arr, x, y);}}}
}/** 冒泡排序*/
public static void bubbleSort(int[] arr) {for (int x = 0; x < arr.length - 1; x++) {for (int y = 0; y < arr.length - x - 1; y++) { // -x让每一次比较的元素减少,-1避免角标越界。if (arr[y] > arr[y + 1]) {// int temp = arr[y];// arr[y] = arr[y + 1];// arr[y + 1] = temp;swap(arr, y, y + 1);}}}
}public static void reverseArray(int[] arr) {for(int start = 0,end = arr.length - 1; start < end; start++, end--) {swap(arr, start, end);}
}public static void printArray(int[] arr) {System.out.print("[");for (int x = 0; x < arr.length; x++) {if (x != arr.length - 1) {System.out.print(arr[x] + ",");} else {System.out.print(arr[x] + "]");}}System.out.println();
}/** 发现无论什么排序。* 都需要对满足条件的元素进行位置置换。 * 所以可以把这部分相同的代码提取出来,单独封装成一个函数。*/
public static void swap(int[] arr, int a, int b) {int temp = arr[a];arr[a] = arr[b];arr[b] = temp;
}
- 折半查找(二分查找)
import java.util.Arrays;/*
数组的查找操作。练习:有一个有序的数组,想要将一个元素插入到该数组中,
还要保证该数组是有序的。如何获取该元素在数组中的位置。
*/public static void main(String[] args) {int[] arr = { 2, 4, 6, 8, 10, 12, 14, 16 };int index = getIndex(arr, 2);System.out.println("index = " + index); // 0int index1 = halfSearch(arr, 32);System.out.println("index1 = " + index1); // -1int index2 = halfSearch_2(arr, 14);System.out.println("index2 = " + index2); // 6int index3 = getIndex_2(arr, 15); System.out.println("index3 = " + index3); // 7int x = Arrays.binarySearch(arr, 11); // Java提供好的一个进行折半查找的功能。开始时使用这个。System.out.println("x = " + x); // -插入点 - 1 = -6}public static int getIndex_2(int[] arr, int key) {int min = 0, max = arr.length - 1, mid;while (min <= max) {mid = (max + min) >> 1;if (key > arr[mid])min = mid + 1;else if (key < arr[mid])max = mid - 1;elsereturn mid;}return min;}/** 折半的第二种方式。*/public static int halfSearch_2(int[] arr, int key) {int min = 0, max = arr.length - 1, mid;while (min <= max) {mid = (max + min) >> 1;if (key > arr[mid])min = mid + 1;else if (key < arr[mid])max = mid - 1;elsereturn mid;}return -1;}/** 折半查找。提高效率,但是必须要保证该数组是有序的数组。*/public static int halfSearch(int[] arr, int key) {int min, max, mid; // 小大中min = 0;max = arr.length - 1;mid = (max + min) / 2;while (arr[mid] != key) {if (key > arr[mid]) {min = mid + 1;} else if (key < arr[mid]) {max = mid - 1;}if (min > max) {return -1;}mid = (max + min) / 2;}return mid;}// 定义功能,获取key第一次出现在数组中的位置。如果返回是-1,那么代表该key在数组中不存在。public static int getIndex(int[] arr, int key) {for (int x = 0; x < arr.length; x++) {if (arr[x] == key) {return x;}}return -1;}
练习进制转换
public static void main(String[] args) {toBin(6);System.out.println(Integer.toBinaryString(60));toHex(60);}/** 十进制 --> 十六进制*/public static void toHex(int num) {StringBuffer sb = new StringBuffer();for (int x = 0; x < 8; x++) {int temp = num & 15;if (temp > 9) {// System.out.println((char) (temp - 10 + 'A'));sb.append((char) (temp - 10 + 'A'));} else {// System.out.println(temp);sb.append(temp);}num = num >>> 4;}System.out.println(sb.reverse());}/** 十进制 --> 二进制*/public static void toBin(int num) {StringBuffer sb = new StringBuffer();while (num > 0) {sb.append(num % 2);num = num / 2;}System.out.println(sb.reverse());}
public static void main(String[] args) {toHex(60);}/** 0 1 2 3 4 5 6 7 8 9 A B C D E F == 十六进制中的元素。 0 1 2 3 4 5 6 7 8 9 10 11 12 13* 14 15* * 查表法:将所有的元素临时存储起来。建立对应关系。 每一次&15后的值作为索引去查建立好的表。就可以找对应的元素。 这样比 -10+'a'简单的多。* * 这个表怎么建立呢? 可以通过数据的形式来定义。 发现终于出结果了。但是是反着的。想要正过来呢?可以通过StringBuffer reverse功能来完成。* 但是这个工具还没有学习。* * 所以可以使用已经学习过额容器,数组来完成存储。*/public static void toHex(int num) {char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };// 定义一个临时容器。char[] arr = new char[8]; // '\u0000'int pos = arr.length;while (num != 0) {int temp = num & 15;arr[--pos] = chs[temp];num = num >>> 4;}// for (int x = 0; x < 8; x++) {// int temp = num & 15;// arr[x] = chs[temp];// num = num >>> 4;// }System.out.println("pos = " + pos);for (int x = pos; x < arr.length; x++) {System.out.print(arr[x]);}}
public static void main(String[] args) {toHex(60); // 3CSystem.out.println();toBin(-6); // 11111111111111111111111111111010System.out.println();}public static void toBin(int num) {// 定义二进制的表char[] chs = { '0', '1' };// 定义一个临时存储容器char[] arr = new char[32];// 顶一个操作数组的指针int pos = arr.length;while (num != 0) {int temp = num & 1;arr[--pos] = chs[temp];num = num >>> 1;}for (int x = pos; x < arr.length; x++) {System.out.print(arr[x]);}}/** 0 1 2 3 4 5 6 7 8 9 A B C D E F == 十六进制中的元素。 0 1 2 3 4 5 6 7 8 9 10 11 12 13* 14 15* * 查表法:将所有的元素临时存储起来。建立对应关系。 每一次&15后的值作为索引去查建立好的表。就可以找对应的元素。 这样比 -10+'a'简单的多。* * 这个表怎么建立呢? 可以通过数据的形式来定义。 发现终于出结果了。但是是反着的。想要正过来呢?可以通过StringBuffer reverse功能来完成。* 但是这个工具还没有学习。* * 所以可以使用已经学习过额容器,数组来完成存储。*/public static void toHex(int num) {char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };// 定义一个临时容器。char[] arr = new char[8]; // '\u0000'int pos = arr.length;while (num != 0) {int temp = num & 15;// System.out.println(chs[temp]);arr[--pos] = chs[temp];num = num >>> 4;}System.out.println("pos = " + pos); // pos = 6// 存储数据的arr数组遍历。for (int x = pos; x < arr.length; x++) {System.out.print(arr[x]);}}
public static void main(String[] args) {toBin(6); // 110toOctal(60); // 74toHex(-60); // FFFFFFC4}// 十进制 --> 二进制public static void toBin(int num) {trans(num, 1, 1);}// 十进制 --> 八进制public static void toOctal(int num) {trans(num, 7, 3);}// 十进制 --> 十六进制public static void toHex(int num) {trans(num, 15, 4);}public static void trans(int num, int base, int offfset) {if (num == 0) {System.out.println(0);return;}char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };char[] arr = new char[32];int pos = arr.length;while (num != 0) {int temp = num & base;arr[--pos] = chs[temp];num = num >>> offfset;}for (int x = pos; x < arr.length; x++) {System.out.print(arr[x]);}System.out.println();}
二维数组
格式1:int[][] arr = new int[3][2]; |
---|
定义了名称为arr的二维数组 |
二维数组中有3个一维数组 |
每一个一维数组中有2个元素 |
一维数组的名称分别为arr[0],arr[1],arr[2] |
给第一个一维数组1角标位赋值为78写法是:arr[0][1] = 78; |
格式2:int[][] arr = new int[3][]; |
---|
二维数组中有3个一维数组 |
每个一维数组都是默认初始化值null |
可以对这个三个一维数组分别进行初始化 |
arr[0] = new int[3];
arr[1] = new int[1];
arr[2] = new int[2];
格式3:int[]arr = {{3,8,2},{2,7},{9,0,1,6}}; |
---|
定义一个名称为arr的二维数组 |
二维数组中的有三个一维数组 |
每一个一维数组中具体元素也都已初始化 |
第一个一维数组arr[0] = {3,8,2}; |
第二个一维数组arr[1] = {2,7}; |
第三个一维数组arr[2] = {9,0,1,6}; |
第三个一维数组的长度表示方式:arr[2].length; |
练习:获取arr数组中所有元素的和。使用for的嵌套循环即可。 |
注意特殊写法情况:int[]x,y[];x是一维数组,y是二维数组。 |
int[] arr1 = new int[3]; // 一维数组// 定义了名称为arr的二维数组。二维数组中有3个一维数组。每一个一维数组中有四个元素。int[][] arr2 = new int[3][4];int[][] arr3 = new int[3][];arr3[0] = new int[3];arr3[1] = new int[1];arr3[2] = new int[2];System.out.println(arr3); // [[I@52e922System.out.println(arr3[0]); // [I@25154fSystem.out.println(arr3[0][0]); // 0// 打印是二维数组的长度System.out.println(arr3.length); // 3// 打印二维数组中第一个一维数组长度System.out.println(arr3[0].length);int[][] arr4 = { { 3, 5, 1, 7 }, { 2, 3, 5, 8 }, { 6, 1, 8, 2 } };int sum = 0;for (int x = 0; x < arr4.length; x++) {for (int y = 0; y < arr4[x].length; y++) {sum += arr4[x][y];}}System.out.println("sum = " + sum);int[] x;int x[];int[][] y;int y[][];int[] y[];int[] x,y[]; // x一维,y二维int[] x;int[] y[];x[0] = y; // error y[0] = x; // yesy[0][0] = x; // errorx[0][0] = y; // errory[0][0] = x[0]; // yex = y; // error
第三章 面向对象
- 面向对象概念
- 类与对象的关系
- 封装
- 构造函数
- this关键字
- static关键字
- 单例设计模式
面向对象概念
- 理解面向对象
- 面向对象的特点
理解面向对象
- 面向对象是相对面向过程而言
- 面向对象和面向过程都是一种思想
- 面向过程
- 强调的是功能行为
- 面向对象
- 将功能封装进对象,强调具备了功能的对象。
- 面向对象是基于面向过程的。
面向过程:打开冰箱 -> 存储进冰箱 -> 关闭冰箱
面向对象:冰箱.打开 -> 冰箱.存储 -> 冰箱.关闭
面向对象的特点
- 是一种符合人们思考习惯的思想
- 可以将复杂的事情简单化
- 将程序员从执行者转换成了指挥者
- 完成需求时:
- 先要去找具有所需的功能的对象来用。
- 如果该对象不存在,那么创建一个具有所需功能的对象。
- 这样简化开发并提高复用。
面向对象开发,设计,特征
- 开发的过程:其实就是不断的创建对象,使用对象,指挥对象做事情。
- 设计的过程:其实就是在管理和维护对象之间的关系。
- 面向对象的特征:
- 封装(encapsulation)
- 继承(inheritance)
- 多态(polymorphism)
类与对象的关系
- 使用计算机语言就是不断的在描述现实生活中的事物。
- Java中描述事物通过类的形式体现,类是具体事物的抽象,概念上的定义。
- 对象即是该类事物实实在在存在的个体。
/*人开门:名词提炼法。
*/
人{开门(门){门.开():}
}
门{开(){操作门轴等。}
}
类与对象(图例)
类的定义
- 生活中描述事物无非就是描述事物的属性和行为。
- 如:人有身高,体重等属性,有说话,打球等行为。
- Java中用类class来描述事物也是如此
- 属性:对应类中的成员变量。
- 行为:对应类中的成员函数。
- 定义类其实在定义类中的成员(成员变量和成员函数)。
成员变量和局部变量的区别?
- 成员变量:
- 成员变量定义在类中,在整个类中都可以被访问。
- 成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
- 成员变量有默认初始化值。
- 局部变量:
- 局部变量只定义在局部范围内,如:函数内,语句内等。
- 局部变量存在于栈内存中。
- 作用的范围结束,变量空间会自动释放。
- 局部变量没有默认初始化值。
创建对象,使用对象
public class Car { // 对Car这类事物进行描述String color = "red";int num = 4;void show() {System.out.println("color = " + color + "..num = " + num); // color = black..num = 4
}class CarDemo {public static void main(String[] args) {demo c = new demo(); // 建立对象c.color = "black"; // 对象的属性进行修改c.show(); // 使用对象的功能。}
}
对象内存结构
匿名对象
- 匿名对象是对象的简化形式
- 匿名对象两种使用情况
- 当对对象方法仅进行一次调用的时候
- 匿名对象可以作为实际参数进行传递
/** 面向对象:三个特征:封装,继承,多态。* 以后开发:其实就是找对象使用。没有对象,就创建一个对象。* 找对象,建立对象,使用对象。维护对象的关系。* * 类和对象的关系。* 现实生活中的对象:张三 李四。* 想要描述:提取对象中共性内容。对具体的抽象。* 描述时:这些对象的共性有:姓名,年龄,性别,学习Java功能。* * 映射到Java中,描述就是class定义的类。* 具体对象就是对应Java在堆内存中用new建立实体。* * 类就是:对现实生活中事物的描述。* 对象:就是这类事物,实实在在存在个体。* */// 需求:描述汽车(颜色,轮胎数)。描述事物其实就是在描述事物的属性和行为。
// 属性对应是类中变量,行为对应类中的函数(方法)。
// 定时定义类,就是在描述事物,就是在定义属性和行为。属性和行为共同成为类中的成员(成员变量和成员方法)。/** 成员变量和局部变量* 作用范围:* 成员变量作用于整个类中。* 局部变量作用于函数中,或者语句中。* 在内存中的位置:* 成员变量:在堆内存中,因为对象的存在,才在内存中存在。* 局部变量:存在栈内存中。* */
public class Car {// 描述颜色String color = "red";// 描述轮胎数int num = 4;// 运行行为void run() {System.out.println(color + ".." + num);}public static void main(String[] args) {// 生产汽车。在Java中通过new操作符来完成。// 其实就是在堆内存产生一个实体。Car c = new Car(); // c就是一个类类型变量。记住:类类型变量指向对象。// 需求:将已有车的颜色改成蓝色。指挥该对象做使用。在Java指挥方式是:对象.对象成员c.color = "blue";c.run(); // blue..4Car c1 = new Car();c1.run(); // red..4Car c2 = new Car();c2.num = 5;Car c3 = c2;c3.color = "green";c3.run(); // green..5c2.run(); // green..5new Car().num = 5;new Car().color = "blue";new Car().run(); // red.4Car c4 = new Car();c4.run(); // red..4c4.num = 4;new Car().run(); // red..4/** 匿名对象是用方式一: 当对对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。 如果对一个对象进行多个成员调用,必须给这个对象起个名字。* 匿名对象使用方式二: 可以将匿名对象作为实际参数进行传递。*/Car q = new Car();show(q); // black..3show(new Car()); // black..3}// 需求:汽车修配厂。对汽车进行改装,将来的车都改成黑车,三个轮胎。public static void show(Car c) {c.num = 3;c.color = "black";c.run();}
}
封装(Encapsulation)
- 封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
- 好处:
- 将变化隔离。
- 便于使用。
- 提高重用性。
- 提高安全性。
- 封装原则:
- 将不需要对外提供的内容都隐藏起来。
- 把属性都隐藏,提供公共方法对其访问。
private(私有)关键字
- private关键字:
- 是一个权限修饰符。
- 用于修饰成员(成员变量和成员函数)
- 被私有化的成员只在本类中有效。
- 常用之一:
- 将成员变量私有化,对外提供对应的set,get方法对其进行访问。提高对数据访问的安全性。
/** private:私有,权限修饰符:用于修饰类中的成员(成员变量,成员函数。)* 私有只在本类中有效。* * 将age私有化以后,类以外即使建立了对象也不能直接访问。* 但是人应该有年龄,就需要在Person类提供对应访问age的方式。* * 注意:私有仅仅是封装的一种表现形式。* * 之所以对外提供访问方式,就因为可以在访问方式中加入逻辑判断等语句。* 对访问的数据进行操作。提高代码健壮性。* */
class Person {private int age;public void setAge(int a) {if (a > 0 && age < 130) {age = a;speak();} else {System.out.println("非法年龄");}}public int getAge() {return age;}void speak() {System.out.println("age = " + age);}
}class PersonDemo {public static void main(String[] args) {Person p = new Person();// p.age = -20;p.setAge(20); // age = 20p.setAge(-20); // 非法年龄// p.speak();}
}
构造函数
特点:
- 函数名与类名相同
- 不用定义返回值类型
- 不可以写return语句
作用:给对象进行初始化。
注意:
- 默认构造函数的特点。
- 多个构造函数是以重载的形式存在的。
构造函数、构造代码块
/** 对象一建立就会调用与之对应的构造函数。* * 构造函数的作用:可以用于给对象进行初始化。* * 构造函数的小细节:* 当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。* 当在类中自定义了构造函数后,默认的构造函数就没有了。* * 构造函数和一般函数在写法上不同。* 在运行上也有不同。* 构造函数时在对象一建立就运行。给对象初始化。* 而一般方法是对象调用才执行,是给对象添加对象具备的功能。* * 什么时候定义构造函数呢?* 当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。* */
class Person {private String name;private int age;/** 构造代码块。 * 作用:给对象进行初始化。 * 对象一建立就运行,而且优先于构造函数执行。 * 和构造函数的区别: * 构造代码块是给所有对象进行统一初始化。* 而构造函数是给对应的对象初始化。 * 构造代码块中定义的是不同对象共性的初始化内容。*/{System.out.println("person code run");cry();}public void setName(String n) {name = n;}public String getName() {return name;}public void setAge(int a) {age = a;}public int getAge() {return age;}public Person() {System.out.println("A: name = " + name + ",age = " + age);}public Person(String n) {name = n;System.out.println("B: name = " + name + ",age = " + age);}public Person(String n, int a) {name = n;age = a;System.out.println("C: name = " + name + ",age = " + age);}public void cry() {System.out.println("cry......");}}
class PersonDemo2 {public static void main(String[] args) {// person code run// cry......// A: name = null,age = 0Person p1 = new Person();// p1.cry();// person code run// cry......// B: name = lisi,age = 0// 3// libusiPerson p2 = new Person("lisi");p2.setAge(3);p2.setName("libusi");System.out.println(p2.getAge());System.out.println(p2.getName());// person code run// cry......// C: name = wangwu,age = 3Person p3 = new Person("wangwu", 3);}
}
this关键字
- 特点:this代表其所在函数所属对象的引用。
- 换言之:this代表本类对象的引用。
- 什么时候使用this关键字呢?
- 当在函数内需要用到调用该函数的对象时,就用this。
this关键字的应用
/** this:看上去,是用于区分局部变量和成员变量同名情况。* this为什么可以解决这个问题?* this到底代表的是什么呢?* * this:就代表本类的对象,到底代表哪一个呢?* this代表它所在函数所属对象的引用。* 简单说:哪个对象在调用this所在的函数,this就代表哪个对象。* this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。* 但凡本类功能内部使用了本来对象,都用this表示。* */
class Person {private String name;private int age;public Person(int age) {this.age = age;}public Person(String name) {this.name = name;}public Person(String name, int age) {this.name = name;this.age = age;}public void speak() {System.out.println("name = " + this.name + "..age = " + this.age);show();}public void show() {System.out.println(this.name);}/** 需求:给人定义一个用于比较年龄是否相同的功能。也就是是否同龄人。*/public boolean compare(Person p) {return this.age == p.age;}
}
class PersonDemo3 {public static void main(String[] args) {Person p = new Person("lisi");Person p1 = new Person("zhangsan");// name = lisi..age = 0// lisip.speak();// name = zhangsan..age = 0// zhangsanp1.speak();// name = ss..age = 0// ssnew Person("ss").speak();Person p2 = new Person(12);Person p3 = new Person(12);boolean b = p2.compare(p3);System.out.println(b); // true}
}
this关键字在构造函数间调用
/** this语句:用于构造函数之间进行互相调用。* this语句只能定义在构造函数的第一行。因为初始化要先执行。* */
class Person {private String name;private int age;{System.out.println("code run");}Person() {System.out.println("person run");}Person(String name) {this();this.name = "haha";}Person(String name, int age) {this(name); // p(name)this.name = name;this.age = age;}public void speck() {System.out.println(name + ".." + age);}
}
class PersonDemo4 {public static void main(String[] args) {Person p = new Person("lisi1", 30);p.speck(); // code run/person run/lisi1..30Person p1 = new Person("lisi2", 36);p1.speck(); // code run/person run/lisi2..36}
}
static(静态)关键字
- static关键字:
- 用于修饰成员(成员变量和成员函数)
- 被修饰后的成员具备以下特点:
- 随着类的加载而加载
- 优先于对象存在
- 被所有对象所共享
- 可以直接被类名调用
- 使用注意
- 静态方法只能访问静态成员
- 静态方法中不可以写this,super关键字
- 主函数是静态的
/** 静态:static* 用法:是一个修饰符,用于修饰成员(成员变量,成员函数)。* 当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外。* 还可以直接被类名调用。类名.静态成员。* * static特点:* 1. 随着类的加载而加载* 也就说,静态会随着类的消失而消失,说明它的生命周期最长。* 2. 优先于对象存在* 明确一点,静态是先存在,对象是后存在的。* 3. 被所有对象所共享* 4. 可以直接被类名所调用* * 实例变量和类变量的区别:* 1. 存放位置:* 类变量随着类的加载而存在于方法区中。* 实例变量随着对象的建立而存在于堆内存中。* 2. 生命周期:* 类变量生命周期最长,随着类的消失而消失。* 实例变量生命周期随着对象的消失而消失。* * 静态使用注意事项:* 1. 静态方法只能访问静态成员。* 非静态方法即可以访问静态也可以访问非静态。* 2. 静态方法中不可以定义this,super关键字。* 因为静态优先于对象存在,所以静态方法中不可以出现this。* 3. 主函数是静态的。* * 静态有利有弊:* 利处:对对象共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。* 可以直接被类名调用。* 弊端:生命周期过长* 访问出现局限性(静态虽好,只能访问静态。)* */
class Person {String name; // 成员变量(实例变量)static String country = "CN"; // 静态的成员变量(类变量)public void show() {System.out.println(name + "::" + country); // lisi::CNSystem.out.println(this.country); // CNhaha();}public static void show1() {System.out.println(country); // CN// System.out.println(this.country); // error// System.out.println(name + "::" + country); // error// haha(); // error}public void haha() {}
}
class StaticDemo {public static void main(String[] args) {Person p = new Person();p.name = "lisi";p.show(); System.out.println(p.country); // CNSystem.out.println(Person.country); // CNPerson.show1();}
}
main函数
/** public static void main(String[] args)* * 主函数:是一特殊的函数,作为程序的入口,可以被Java使用。* * 主函数的定义:* public:代表着该函数访问权限是最大的。* static:代表主函数随着类的加载就已经存在了。* void:主函数没有具体的返回值。* main:不是关键字,但是是一个特殊的单词,可以被jvm识别。* (String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。* * 主函数是固定格式的:jvm识别。* * jvm在调用主函数时,传入的是new String(0);*/
class MainDemo {public static void main(String[] arguments) { // new String[]System.out.println(arguments); // [Ljava.lang.String;@52e922System.out.println(arguments.length); // 0// System.out.println(arguments[0]); // java.lang.ArrayIndexOutOfBoundsException越界String[] arr = { "haha", "hehe", "xixi", "heihei", "giaogiao", "hiahia" };MainTest.main(arr);}
}
class MainTest {public static void main(String[] args) {for (int x = 0; x < args.length; x++) {System.out.println(args[x]);}}
}
静态是什么时候使用?
/** 什么时候使用静态?* * 要从两方面下手:* 因为静态修饰的内容有成员变量和成员函数。* 什么时候定义静态变量(类变量)呢?* 当对象中的出现共享数据时,该数据被静态所修饰。* 对象中的特有数据要定义成非静态存在于堆内存中。* 什么时候定义静态函数(类函数)呢?* 当功能内部没有访问到非静态数据(对象的特有数据),* 那么该功能可以定义成静态的。* */
静态的应用-工具类
/** 静态的应用:* * 每一个应用程序中都有共性的功能* 可以将这些功能进行抽取,独立封装。以便复用。* * 虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。* 发现了问题:* 1. 对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。* 2. 操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。* * 这时就考虑,让程序更严谨,是不需要对象的。* 可以将ArrayTool中的方法都定义成static的,直接通过类名调用即可。* * 将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象的。* 为了更为严谨,强制让该类不能建立对象。* 可以通过将构造函数私有化完成。* */class ArrayTool {private ArrayTool() {}public static int getMax(int[] arr) {int max = 0;for (int x = 1; x < arr.length; x++) {if (arr[x] > arr[max]) {max = x;}}return arr[max];}public static int getMin(int[] arr) {int min = 0;for (int x = 1; x < arr.length; x++) {if (arr[x] < arr[min]) {min = x;}}return arr[min];}public static void selectSort(int[] arr) {for (int x = 0; x < arr.length - 1; x++) {for (int y = x + 1; y < arr.length; y++) {if (arr[x] > arr[y]) {swap(arr, x, y);}}}}public static void bubblesort(int[] arr) {for (int x = 0; x < arr.length - 1; x++) {for (int y = 0; y < arr.length - x - 1; y++) {if (arr[y] > arr[y + 1]) {swap(arr, y, y + 1);}}}}private static void swap(int[] arr, int a, int b) {int temp = arr[a];arr[a] = arr[b];arr[b] = temp;}public static void printArray(int[] arr) {System.out.print("[");for (int x = 0; x < arr.length; x++) {if (x != arr.length - 1) {System.out.print(arr[x] + ", ");} else {System.out.print(arr[x] + "]\n");}}}
}
public class ArrayToolDemo {public static void main(String[] args) {int[] arr = { 1, 3, 9, 4, 2 };int max = ArrayTool.getMax(arr);System.out.println("max = " + max); // 9// ArrayTool tool = new ArrayTool();/** ArrayTool tool = new ArrayTool(); * int max = tool.getMax(arr);* System.out.println("max = " + max); // 9 * int min = tool.getMin(arr);* System.out.println("min = " + min); // 1 * tool.printArray(arr); // [1, 3, 9,4, 2] * tool.selectSort(arr); * tool.printArray(arr); // [1, 2, 3, 4, 9]*/}
}
帮助文档的制作JavaDOC
javadoc -d myhelp -author -version ArrayTool.java
/*** 接下来,将ArrayTool.class文件发送给其他人,其他人只要将该文件设置到classpath路径下,就可以使用该工具类。* 但是,很遗憾,该类中到底定义了多少个方法,对方却不清除,因为该类并没有使用说明书。* 开始制作程序的说明书,Java的说明书通过文档注释来完成。*//*** 这是一个可以对数组进行操作的工具类,该类中提供了,获取最值,排序等功能。* * @author bing* @version v1.1*/
public class ArrayTool {/*** 空参数构造函数*/private ArrayTool() {}/*** 获取一个整型数组中的最大值。* * @param arr* 接收一个int类型的数组* @return 会返回一个该数组中最大值。*/public static int getMax(int[] arr) {int max = 0;for (int x = 1; x < arr.length; x++) {if (arr[x] > arr[max]) {max = x;}}return arr[max];}/*** 获取一个整型数组中的最小值。* * @param arr* 接收一个int类型的数组* @return 会返回一个该数组中最小值。*/public static int getMin(int[] arr) {int min = 0;for (int x = 1; x < arr.length; x++) {if (arr[x] < arr[min]) {min = x;}}return arr[min];}/*** 给int数组进行选择排序。* * @param arr* 接收一个int类型的数组*/public static void selectSort(int[] arr) {for (int x = 0; x < arr.length - 1; x++) {for (int y = x + 1; y < arr.length; y++) {if (arr[x] > arr[y]) {swap(arr, x, y);}}}}/*** 给int数组进行冒泡排序。* * @param arr* 接收一个int类型的数组*/public static void bubblesort(int[] arr) {for (int x = 0; x < arr.length - 1; x++) {for (int y = 0; y < arr.length - x - 1; y++) {if (arr[y] > arr[y + 1]) {swap(arr, y, y + 1);}}}}/*** 给数组中元素进行位置的置换。* * @param arr* 接收一个int类型的数组* * @param a* 变量换的位置* * @param b* 变量换的位置*/private static void swap(int[] arr, int a, int b) {int temp = arr[a];arr[a] = arr[b];arr[b] = temp;}/*** 用于打印数组中的元素。打印形式是:[elemet1, elemet2, ...]*/public static void printArray(int[] arr) {System.out.print("[");for (int x = 0; x < arr.length; x++) {if (x != arr.length - 1) {System.out.print(arr[x] + ", ");} else {System.out.print(arr[x] + "]\n");}}}
}/** 一个类中默认会有一个空参数的构造函数,这个默认的构造函数的权限和所属类一致。* 如果类被public修饰,那么默认的构造函数也带public修饰符。* 如果类没有被public修饰,那么默认的构造函数,也没有public修饰。* * 默认构造函数的权限是随着类的变化而变化的。*/
静态代码块
/** 静态代码块。* 格式:* static {* 静态代码块中的执行语句。* }* 特点:随着类的加载而执行,只执行一次,并优先于主函数。* 用于给类进行初始化的。* */
class StaticCode {int num = 9;public StaticCode() {System.out.println("b");}static {System.out.println("a");}{System.out.println("c" + this.num);}StaticCode(int x) {System.out.println("d");}public static void show() {System.out.println("show run");}
}class StaticCodeDemo {static {System.out.println("b");}public static void main(String[] args) {new StaticCode();new StaticCode();System.out.println("over"); StaticCode.show();StaticCode a = null;a = new StaticCode();new StaticCode(4);}static {System.out.println("c");}
}
运行结果
b
c
a
c9
b
c9
b
over
show run
c9
b
c9
d
对象的初始化过程
class Person {public Person() {}private String name = "hah";private int age;private static String country = "cn";Person(String name, int age) {this.name = name;this.age = age;}{System.out.println(name + ".." + age);}public void setName(String name) {this.name = name;}public void speak() {System.out.println(this.name + "..." + this.age);}public static void showCountry() {System.out.println("country=" + Person.country);Person.method();}public static void method() {System.out.println("method run");}
}public class PersonDemo {public static void main(String[] args) {Person p = new Person("zhangsan", 20);p.setName("lisi");new Person();}
}
/** Person p = new Person("zhangsan", 20); * 该句话都做了什么事情?* 1. 因为new用到了Person.class文件,所以会先找到Person.class文件并加载到内存中。 * 2. 会执行该类中的static代码块,如果有的话,给Person.class类进行初始化。* 3. 在堆内存中开辟空间,分配内存地址。 * 4. 在堆内存中建立对象的特有属性,并进行默认初始化。 * 5. 对属性进行显示初始化。 * 6. 对对象进行构造代码块初始化。 * 7. 对对象进行对应的构造函数初始化。* 8. 将内存地址赋给栈内存中的p变量。*/
单例设计模式
/** 设计模式:解决某一类问题最行之有效的方法。* Java中23种设计模式:* 单例设计模式:解决一个类在内存中只存在一个对象。* * 想要保证对象唯一。* 1. 为了避免其他程序过多建立该类对象,先禁止其他程序建立类对象。* 2. 还为了让其他程序可以访问到该类对象,只好在本类中自定义一个对象。* 3. 为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。* * 这三步怎么用代码体现呢?* 1. 将构造函数私有化。* 2. 在类中创建一个本类对象。* 3. 提供一个方法可以获取该对象。* * 对于事物该怎么描述,还怎么描述。* 当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可。* * */
class Single {private int num;public void setNum(int num) {this.num = num;}public int getNum() {return num;}private Single() {}private static Single s = new Single();public static Single getInstance() {return s;}
}class SingleDemo {public static void main(String[] args) {Single ss = Single.getInstance();System.out.println(ss); // test9.Single@52e922// Single s1 = new Single();// Single s2 = new Single();// s1.setNum(40);// System.out.println(s2.getNum()); // 0Single s1 = Single.getInstance();Single s2 = Single.getInstance();s1.setNum(23);System.out.println(s2.getNum()); // 23// Student s1 = new Student();// s1.setAge(30);// Student s2 = new Student();// s2.setAge(12);// Student s1 = Student.getInstance();// Student s2 = Student.getInstance();}
}class Student {private int age;private Student() {}private static Student s = new Student();public static Student getInstance() {return s;}public void setAge(int age) {this.age = age;}public int getAge() {return age;}
}
单例设计模式方式二
/** 这个是先初始化对象。* 称为:饿汉式。* * Single类一进内存,就已经创建好了对象。* */
class Single {private static Single s = new Single();private Single() {}public static Single getInstance() {return s;}}/** 对象是方法被调用时,才初始化,也叫做对象的延时加载。* 称为:懒汉式。* Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。* */
class Single {private static Single s = null;private Single() {}public static Single getInstance() {if(s==null) {synchronized(Single.class) {if (s == null) {s = new Single();}}}return s;}
}/** 记录原则:定义单例,建议使用饿汉式。* */
毕向东Java笔记(全部)相关推荐
- 【JAVA】毕向东Java基础视频教程-笔记
传智播客-毕向东Java基础视频教程 <2013年-33days>版-学习代码记录 链接: GitHub库:JavaBXD33 目录 01-Java基础知识 02-Java对象细节 03- ...
- 黑马毕向东Java课程笔记(day20-1——20-17)IO流:File类及相关方法、递归、递归的相关练习、Properties、PrintWriter类与PrintStream类、合并流与切割流
1.File类概述 File是文件和目录路径名的抽象表示形式. 用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作. 前面说到的"流",它只能操作数据,想 ...
- 黑马毕向东Java课程笔记(day14-1——14-11):集合类(集合框架)——集合类分类与特点+List集合接口及其子类
1.集合类特点 为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 数组和集合类同是容器,有何不同 ...
- 黑马毕向东Java课程笔记(day16-1-16-9):集合类(集合框架)——Map集合
1.Map集合 Map集合的基本特点如下: 接口 Map<K,V>:将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值.(但是值可以重复) K - 此映射所维护的 ...
- 黑马毕向东Java课程笔记(day19-11——19-22)IO字节流:字节流及其读取、字节流缓冲区、自定义字节流(读取)的缓冲区、读取键盘的输入、读取/写入转换流、流操作规律
1.字节流--File 字节流的介绍 字符流:(一个字符2个字节16位) FileReader FileWriter. BufferedReader BufferedWriter字节流:(一个字节 ...
- 黑马毕向东Java课程笔记(day07):面向对象(第三部分)继承+抽象类+模板方法设计模式+接口+final+继承补充(就业班)
在这一部分中,我们将讲解有关继承的相关内容,包括继承的概述.继承的特点.super关键字.函数覆盖.子类的实例化过程.final关键字这几个部分的内容. 1.继承的概述以及特点 1.1.概述 ...
- 黑马毕向东Java课程笔记(day11):多线程(第一部分)——进程与线程+线程创建+线程安全与同步代码块+同步锁/死锁
多线程好文:添加链接描述 锁机制:synchronized.Lock.Condition.volatile(原子性可见性)--参考添加链接描述 1.进程与线程概述 首先,对于CPU执行每一个程序, ...
- 内部类--毕向东Java基础教程学习笔记
内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...
- 毕向东java基础笔记
函数功能: pubic void getSum(int x, int y) { int ret = x+y; System.out.println(ret); } 这个功能定义的思想有问题,因为只为完 ...
- 毕向东—Java基础知识总结(超级经典)
Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...
最新文章
- C++ 笔记(32)— 预处理、文件包含include、宏替换define、条件包含ifndef、define
- opencv配置(转)
- python对文件的读操作方法有哪些-Python文件操作实例大全
- 自定义Dictionary支持线程安全
- 设置 git pull 无需输入账号和密码
- 命名空间“System.Web”中不存在类型或命名空间名称“Optimization”解决方法
- web 前端小记_1 :hasLayout
- opengl魔方文档_基于OpenGL的3D旋转魔方的实现.doc
- 分享一个好的清理系统垃圾软件
- 一位清华贫困生的“树洞”刷屏!“我想照亮哪怕其他一个人也好”...
- 各大型网站反爬虫策略
- 活动星投票网络文明公益广告网络评选微信的投票方式线上免费投票
- 人工智能在石油勘探开发中的应用及发展趋势(总结部分)
- yxc_第二章 数据结构(一)_kmp算法
- 服务IP(VIP)的作用
- yoyo-rebecca
- 关于统一等价类划分的术语和过程
- 因果系列文章(2):因果推断初探
- 无纸化、自动化、智能化|WMS系统升级你的仓储管理模式
- uni-app新手指南