2021年1月26日
java软件工程师;
jdk:Java开发工具包;(下载下来,自带jvm)
jvm:java虚拟机;
- exit:退出当前Dos命令窗口;
- cls:清除屏幕;
- dir:列出当前目录下的所有子目录/子文件;
- cd:改变路径;
- cd .. 回到上级目录;
- cd \ 直接回到根目录;
- c: 回车 切换盘符;
简单性:Java语言不再支持多继承,c++支持多继承,多继承比较复杂;
c++有指针的概念,Java中屏蔽了;
Java语言底层是由c++实现的,不是c;
面向对象:
Java是纯面向对象的语言。
可移植性(跨平台):
Java程序一次编译,不做任何修改可以在window系统,或者Linux系统上运行。
windows和Linux内核肯定是不相同的,两个操作系统执行指令的原理是不相同的。
让Java程序运行在一台虚拟的计算机上,称作Java虚拟机(jvm)Java虚拟机再和底层的操作系统沟通
Java代码不和操作系统直接进行沟通。【java virtual machine:java虚拟机】
多线程:
健壮性:和垃圾回收机制相同,
自动垃圾回收机制,简称GC
Java运行过程中是自动回收产生得垃圾的,不需要程序员关心。
安全性:
1、编译阶段
- 编译阶段检查Java源程序是否符合Java语法
- 字节码文件不是纯粹的二进制文件,不能直接被操作系统使用
- Java编译阶段过程
编译阶段需在硬盘某个位置建一个.java的源文件(须符合Java语法规则),检查Java源文件是否符合Java语法规则,符合则生成.class文件
使用JDK中自带的javac.exe编译源文件
[javac在Dos命令窗口中使用(javac java源文件路径)
javac是Java的一个编译器工具]
一个.java文件可以通过javac编译生成多个.class文件,删除Java源文件不影响程序的执行。
编译结束之后可以将.class文件拷贝到其他的操作系统上执行[跨平台]
- .java 源文件
- .class 字节码文件 编译 验证源文件是否符合Java语法规范 编译成字节码文件
2、运行阶段(可以在其他操作系统中,跨平台)
2021年1月27日
2021年1月30日
/* 一个Java源程序文件中可以定义多个class
* 一个Java源程序文件当中的public class 不是必须的
* 一个class会定义一个xxx.class字节码文件
* 一个Java源程序文件中定义公开的类的话,只能有一个,且必须与Java源文件名称一致。
* 每个class中都可以编写main方法,设置程序的入口,想执行B.class中的main方法
* - java B
*
*/ 注意:执行B.class,其中必须有main方法,没有则会出现运行阶段的错误
总结一:
1、java的加载与执行;
2、搭建Java开发环境
3、编写HelloWorld程序,编译并运行
4、环境变量path的配置及原理;
5、classpath的原理及配置;
6、Java中的注释
7、class和public class的区别
1)java语言中的标识符:
1、 什么是标识符?
- java源程序中凡是程序员有权利自己命名的单词都是标识符
- 标识符在EditPlus中黑色高亮字体
- 标识符可以标识的元素
* 类名
* 方法名
* 变量名
* 接口名
* 常量名
...
2、标识符命名规则?【不按照这个规则,编译器会报错,这个语法规则】
* 标识符只能由“字母,数字,下划线_,美元符号$”组成
* 不能以数字开头
* 严格区分大小写
* 不能是关键字
* 理论上无长度限制,但理论上不能过长
3、标识符的命名规范? 【只是一种规范,不是语法,不遵守编译器不会报错,】
* 最好见名知义
public class UserService{
public void login(String username,String password){
}
}
* 遵守驼峰式命名方式
SystemService
UserService
CustermerService
* 类名,接口名首字母大写,后面每个单词首字母大写
* 变量名,方法名,首字母小写,后面每个单词首字母大写
* 常量名,全部大写
关于字面值
* 字面值(在Java中叫做字面值,在C语言中,叫做常量)
- 10、100
- 3.14
- false、true
- "abc"
- 'a'
* 字面值就是数据
* 字面值是Java源程序的组成部分之一,包括标识符和关键字都是Java源程序的组成部分。
* 数据在现实生活中是分门别类的,在编程语言中也是分类型的(数据类型)
- 10、100 整型字面值
- 3.14 浮点型字面值
- false、true 布尔型字面值
- "abc" 、"中国人" 字符串型字面值
- 'A'、'人' 字符型字面值
- 注意:
Java中字符串型字面值必须使用""双引号括起来,双引号必须是半角的。
Java中字符型字面值必须使用单''引号括起来,单引号必须是半角的。
总结二:
1、什么是变量?
* 变量本质上是内存中的一块空间,这块空间有“数据类型”、“名字”、“字面值”
* 变量包括三个部分:数据类型、名字、字面值【数据】
* 变量是内存中存储数据的最基本单元。
2、数据类型的作用?
* 不同的数据拥有不同的类型,不同的数据类型底层会分配不同大小的存储空间。
* 数据类型是指导程序在运行阶段分配不同大小的存储空间。
3、变量要求:变量中存储的具体的数据,必须和变量的"数据类型"相一致。
4、定义/声明变量的语法格式:
只要是合法的标识符即可;
变量名遵循的规范:首字母小写,后面每个单词首字母大写;
数据类型 变量名;
int i; int age; int num;
5、变量声明之后,如何赋值?
格式:
变量名 = 字面值;
注意:字面值的数据类型必须和变量名声明的数据类型相一致
例如:int i;
i = 10;
int i = 10;
System.out.println(i); // 10
int i = 100;
System.out.println(i); // 100
int i = 1000;
System.out.println(i); // 1000
6、有了变量的概念之后,内存空间得到了重复利用。
7、通常访问一个变量有两种方式:
* 读取变量中的数据 get/获取
* 修改变量中的数据 set/修改
i = 10 // set
System.out.println(i); // get
1、什么是变量的作用域?
变量的作用域是描述变量的有效范围
在什么范围内可以被访问,出了这个范围就不能被访问了
2、出了大括号就不认识了
- 根据作用域的不同进行分类
局部变量:方法体内声明
【存放在栈内存中】
成员变量:方法体外声明,类体内声明
* 实例变量
【存放在堆内存中】
* 静态变量
【存放在方法区内存中】
- 在不同的作用域当中,变量名可以一样;在同一个作用域当中,变量名不能重名。
静态变量的说明图:
1、 数据类型的作用?
程序当中有很多数据,每个不同的数据,有不同的类型,数据的数据类型不同,占用的存储空间不同。
数据类型的作用:指导JVM在运行程序的时候,分配多大存储空间
2、Java中的数据类型包括:
基本数据类型有四大类八小种
第一类:整数型
byte,int,short,long
第二类:浮点型
float,double
第三类;布尔型
boolean
第四类:字符型
char
3、 关于基本数据类型:
4、字符串不属于基本数据类型 “abc” ,属于“引用数据类型”,字符型属于“基本数据类型”
5、八种基本数据类型所占的内存空间大小
基本数据类型 所占内存空间大小[单位:字节]
------------------------------------------------
byte 1
short 2
int 4
long 8
float(单精度浮点型) 4
double(双精度浮点型) 8
boolean 1
char 2
6、基本数据类型之间的转换:转换规则(六条基本规则)
1、 八种数据类型,除Boolean类型外,其他七种类型都可以相互转换
2、 小容量向大容量转换:自动类型转换;容量从小到大
byte < short < int < long < float < double
< char < 注意:任何浮点型不管占用多少字节容量都大于整数型
char和short表示的种类数相同,但是char可以表示更大的正整数
3、大容量向小容量转换,:强制类型转换,需要强制类型转换符;程序才能编译通过。
但是在运行阶段,有可能会损失精度,谨慎使用
4、当整数型字面值没有超出byte,short,char的取值范围时,可以直接赋值给byte,short,char类型的变量
5、 byte short char进行混合运算时,需要先转换成int类型再进行运算
6、多种数据类型混合运算,先转换成容量最大的那种,再进行运算
// 编译期只检查语法,运算期进行运算
7、计算机在任何情况下只识别二进制,例如:011101001010010010…
【现代计算机底层采用交流电的方式,只有接通,断开两种状态;接通1,断开0,只识别二进制】
8、什么是二进制
* 是一种数据的表示形式
* 十进制是满十进一,二进制是满二进一
例如:0 1 10 11 100 101 110 111 1000
8、字节:
1 byte = 8 bit【1个字节 = 8个比特位】一个比特位就是一个二进制位(一个0或者一个1)
1 KB = 1024 byte
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
1 TB = 1 * 1024 * 1024 * 1024 * 1024 * 8 【1T能存这么些1和0】
9、整数型当中的byte类型,占用1个字节,8个比特位,即8个二进制位。byte类型的取值范围是多少?
* Java中的数字类型,数字有正负之分,所以二进制位中有一个位叫做"符号位",并且这个二进制位
在所有二进制位的最左边,0代表正,1代表负。
* byte类型的最大值:01111111 (10000000[二进制] - 1)
* byte类型的最大值:2的7次方减1 ;结果是: 127
* byte类型最小值:-128【具体的怎么使用二进制,这个和原码,补码,反码相关】
* byte类型的取值范围:-128 ~ 127
* byte类型可以表示256个不同的数字【可以表示256个不同的二进制】
10、二进制和十进制的转换规则
11、计算机只认识二进制,那么如何表示现实生活中的文字?
* byte、short、int、long、float、double、boolean这七种数据类型,底层都是十进制数字,
十进制数字和二进制之间存在一种转换规则。容易表示。
但是char类型是现实生活中的文字,文字和二进制之间"默认"没有转换关系。
为了让计算机认识现实生活中的文字,人为的制定好“二进制”和“文字”之间的对应关系,
称为“字符编码”
计算机最初只支持英文,最早的字符编码是“ASCII码”。
‘a’ ---->97【01100001】
‘A’ ---->65
‘0’ ---->48
‘a’ --(按照ASCII码解码)–> 01100001
01100001 --(按照ASCII编码)–> ‘a’
编码/解码按照同一套字典/对照表,进行编码解码不会出现乱码现象
当编码解码时采用的不是同一套对照表时,就会出现乱码现象【这是出现乱码的根本原因】
12、关于八种数据类型的默认值:
数据类型 默认值
byte/short/int/long 0
float double 0.0
boolean false【在C语言中false是0,true是1】
char \u000
八种数据类型默认值向0看齐
13、 关于Java语言当中的整数型:
byte sort int long
1)、Java语言当中的“整数型字面值”,默认使用int类型处理,要让这个int类型当作“long类型”来处理,
后面加l\L建议使用大写的L;
2)、Java语言当中整数型字面值有三种表示形式:
十进制:是一种缺省默认的方式
八进制:在编写八进制整数型字面值的时候需要以0开始
十六进制:编写十六进制整数型字面值的时候需要以0x开始
// 456整数型字面值被当作int类型,占用4个字节;
// x变量在声明的时候,被声明为long类型,占用8个字节;
// int类型字面值456赋给long类型的x,存在类型转换
// int类型是小容量
// long类型是大容量
// 小容量可以自动转换成大容量,称为自动类型转换机制;
long x = 456;
System.out.println(x);
/*
关于Java语言当中的整数型:
数据类型 占用空间大小 取值范围 默认值
-----------------------------------------------------------
byte 1 -128 ~ 127 0
sort 2 -32768 ~ 32767 0
int 4 -2147483648 ~ 2147483647 0
long 8 0L
-----------------------------------------------------------
1、Java语言当中的“整数型字面值”,默认使用int类型处理,要让这个int类型当作“long类型”来处理,
后面加l\L建议使用大写的L;
2、Java语言当中整数型字面值有三种表示形式:
十进制:是一种缺省默认的方式
八进制:在编写八进制整数型字面值的时候需要以0开始
十六进制:编写十六进制整数型字面值的时候需要以0x开始
*/
public class DataTypeTest04
{
public static void main(String[] args){
int a = 10; // 十进制
int b = 010; // 八进制 整数型字面值以0开头的后面的数字就是八进制
int c = 0x10; // 十六进制 整数型字面值以0x开头的后面的数字就是十六进制
System.out.println(a); // 10
System.out.println(b); // 8
System.out.println(c); // 16
System.out.println(a + b + c); // 34 以十进制的形式输出
// 456整数型字面值被当作int类型,占用4个字节;
// x变量在声明的时候,被声明为long类型,占用8个字节;
// int类型字面值456赋给long类型的x,存在类型转换
// int类型是小容量
// long类型是大容量
// 小容量可以自动转换成大容量,称为自动类型转换机制;
long x = 456;
System.out.println(x);
// 2147483647是int类型,占用4个字节;
// y是long类型占用8个字节,自动类型转换
long y = 2147483647;
System.out.println(y);
// 编译错误:过大的整数
// 2147483648一上来就被当作int类型4个字节处理,但是字面值超出int类型范围
// long z = 2147483648;
// System.out.println(z);
// 处理错误
// 2147483648字面值一上来就当作long类型处理,字面值后面加L
// 2147483648L是8个字节的long类型
// z是long类型,因此一下程序不存在类型转换
long z = 2147483648L;
System.out.println(z);
}
}
/*
关于Java语言当中整数型
byte
short
int
long
原码,1100110011
反码,1011001100(除符号位,按位取反)
补码,1011001101(负数的补码:除符号位,按位取反再加1)正整数的补码与其原码相同
*/
public class DataTypeTest05
{
public static void main(String[] args){
// 100是long类型字面值
// x是long类型字面值
// 不存在类型转换
long x = 100L;
// 大容量向小容量转换,需要强制类型转换
// 强制类型转换需要加“强制类型转换符”
// 大容量向小容量强制类型转换会损失精度
// 谨慎使用
// 以下代码编译报错,大容量不能直接赋值给小容量,需要加强制类型转换符。
// int y = x;
// 强转原理
// 原始数据:00000000 00000000 00000000 00000000 00000000 00000000 01100100
// 强转之后的数据:00000000 00000000 00000000 01100100
// 将左边的二进制砍掉【所用的数据强转都是一样的】
int y = (int)x;
System.out.println(y);
// 原始数据: 00000000 00000000 00000000 00000000 100000000 00000000 00000000 00000000
// 强转之后的数据:100000000 00000000 00000000 00000000
// 计算机存储数据都是采用补码的形式存储数据,100000000 00000000 00000000 00000000以补码的形式存储在计算机中
// 所以100000000 00000000 00000000 00000000现在是补码的形式
// 将补码转换成原码就是最终结果
long k = 2147483648L;
int e = (int)k;
System.out.println(e); // 损失精度严重,结果为负数【-2147483648】
// 50是int类型字面值,b是byte类型字面值,显然是大容量转小容量,需要强制类型转换符
// 但是在实际编译中,可以编译通过,只要在byte类型的取值范围中就可以
byte b = 50; // 编译通过
byte b1 = 127; // 编译通过
byte b2 = 128; // 编译报错
/*
当一个整数型字面值没有超出 byte short char 的取值范围,可以直接赋值给byte short char 类型的变量
这种机制SUN允许了,目的是方便程序员编程
*/
}
}
/*
Java数据类型之数据类型:char
*/
public class DataTypeTest01
{
public static void main(String[] args){
// 定义一个char类型的变量,起名为c,赋值为‘a’
char c = 'a';
char x = '国';
System.out.println(c);
// 一个中文占用2个字节,一个char类型变量刚好2个字节
// 所以Java中的char类型变量可以存储一个中文字符
System.out.println(x);
// 编译错误
// ab是字符串,不能使用单引号括起来
// char y = 'ab';
// 类型不兼容,需要的char给出的是String
// char z = "a";
}
}
/*
关于八种数据类型的默认值:
数据类型 默认值
byte/short/int/long 0
float double 0.0
boolean false【在C语言中false是0,true是1】
char \u000
八种数据类型默认值向0看齐
*/
public class DataTypeTest02
{
// 必须加static
static int k = 1000; // 成员变量
static int f; // 成员变量
public static void main(String[] args){
System.out.println(k);
// 成员变量没有手动赋值的时候系统会默认赋值【局部变量不会默认赋值】(没有违背变量需要先声明,再赋值才能访问,只不过是系统默认赋值)
System.out.println(f); // 0
/*
必须声明并赋值才可以访问,没有赋值不能访问
int i; // 局部变量
System.out.println(i);
*/
}
}
/*
关于Java语言中的char类型:
转义字符 \
转义字符出现在特殊字符之前,会将特殊字符转义成普通字符
\n 换行符
\t 制表符
\\ 普通的反斜杠
\' 普通的单引号
\" 普通的双引号
*/
public class DataTypeTest03
{
public static void main(String[] args){
char c1 = 'n'; // 普通的n
System.out.println(c1);
// 反斜杠在Java语言中具有转义功能
char c2 = '\n'; // 此处的\n不是字符串而是"换行符"、是char类型,【占一个字符】
System.out.println(c2);
// System.out.print()和System.out.println()的区别:
// print()表示输出之后不换行,println()表示输出之后换行
/*
System.out.print("Hello");
System.out.println("World!");
System.out.println("Hello");
System.out.println("World!");
*/
// 制表符tab:\t
// tab和空格不同,体现的ASCII不一样
char y = '\t';
System.out.print('A');
System.out.print(y);
System.out.println('B');
// 在控制台上输出一个普通的反斜杠字符“\”
// 编译报错,反斜杠将后一个单引号转义成普通的单引号字符
// char b = '\';
// System.out.print(b);
// 第一个反斜杠将后一个反斜杠转义成普通的反斜杠字符
char a = '\\';
System.out.println(a);
// 在控制台上输出一个普通的单引号字符
char c = '\''; // 转义字符将其后面的单引号字符转义成普通的单引号字符
System.out.println(c);
// 在控制台输出带英文双引号的HelloWorld!
System.out.println("“HelloWorld!”"); // 中文的双引号
System.out.println("\"HelloWorld!\""); // 英文的双引号
// 命令:native2ascii.exe 将中文转换成unicode编码形式
}
}
/*
十进制:
二进制:0 1 10 11 110 111 1110 1111 ...
十六进制:0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20
满十六进一
八进制:0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 ...
满八进一
*/
/*
关于浮点型数据类型:
float : 单精度 4个字节
double:双精度 8个字节(比较而言精度较高)
double类型精度较低,不适合做财务,SUN给程序员准备了引用数据类型
java.math.BigDecimal
SE类库源码:C:\Program Files\Java\jdk-14.0.2\lib\src.zip
SE类库字节码:
例如:
String.java 和 String.class
我们得(String[] args)中得String就是使用得String.class字节码文件
在Java语言当中所有的浮点型字面值都被当作double类型来处理,
要想该字面值当作float类型来处理,在字面值后加F\f即可
注意:double和float在计算机中存储的时候都是近似值
*/
public class DataTypeTest06
{
public static void main(String[] args){
// d是double类型的字面值
// 3.0是double类型的字面值
// 不存在类型转换
double d = 3.0;
// 编译报错
// f是float类型的字面值
// 5.1是double类型的字面值
// 大容量向小容量转换要加强制类型转换符
// float f = 5.1;
// 解决方案:
// 第一种方案:
float f = (float)5.1; // 强制类型转换
// 第二种方案:
float f = 5.1F; // 没有类型转换
}
}
/*
Java语言当中数据类型:
关于布尔型数据类型:boolean
在Java语言当中Boolean只有两个值:true false 不像C语言可以用0和1表示假真
在底层存储的时候boolean类型占用一个字节,因为实际存储的时候,true是1,false是0;
boolean类型在实际开发中非常重要,常用在逻辑运算,条件控制语句当中
*/
public class DataTypeTest07
{
public static void main(String[] args){
// 编译错误:不兼容的类型 int无法转换为boolean
// boolean flag = 1;
boolean loginSuccess = true;
if(loginSuccess){ // if条件控制语句
System.out.println("恭喜你!登录成功!!");
}else{
System.out.println("登录失败,用户名不存在,或者密码错误!!");
}
}
}
类
接口
数组
字符串
…
控制语句:
选择结构:
for
while
do…while
控制循环语句:
break
continue
2021/3/6
break:
1、break是Java语言的一个关键字,意为“中断/折断”
2、break;可以称为一个单独的语句
3、break用在switch语句中用来中止是switch语句的执行
4、break同样可以用在循环语句中,用来终止循环语句的执行
5、break用在for、while、do…while中用来跳出循环,终止当前循环执行
6、默认情况下break终止离他最近的循环。
练习题:
编写for循环输出1 ~ 100 中的所有素数,并每8个素数换一行[可以被自身及1整除的数,不能被其他数整除的数]
2 3 5 7 9 11 13 17 …
实现思路:
7 / 1【不需要】
7 / 2
7 / 3
7 / 4
7 / 5
7 / 6
7 / 7【不需要】
知识点:
* for循环
* for循环的嵌套
* 标记
* break的使用
* 统计机制
引用数据类型:
String是典型的引用数据类型
特点:
1、可以在变量初始化的时候赋值为null,赋值为null表示这个引用类型变量中保存的地址为空;
2、引用数据类型和基本数据类型的区别:
int i1= 1;
int i2= 2;
i1、i2会在内存中存储两个1的值
String j1 = "hello";
String j2 = "hello";
这种只能在内存中存储一个hello值【两个变量用一块相同的内存地址】
2021/3/8
Java语言基础:
/*
java语言当中的条件控制语句\分支语句;属于选择结构;
1、四种编写方式;
第一种结构:
if(布尔表达式){
Java语句;
Java语句;
Java语句;
...
}
第二种结构:
if(布尔表达式){
Java语句;
Java语句;
Java语句;
...
}else{
Java语句;
Java语句;
...
}
第三种结构:
if(布尔表达式){
java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}
...
第四种编写方式:
if(布尔表达式){
java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}else if(布尔表达式){
Java语句;
Java语句;
...
}else{
Java语句;
...
}
2、重点:java语言当中的if语句,只要有一个分支执行,整个if语句结束
3、注意:带有else的if语句,肯定有一个分支执行
4、所有的"控制语句"都是可以嵌套使用的
5、if语句中有一条Java语句,大括号可以省略不写
if(true\false){
一条Java语句;
}
if(true\false)一条java语句;
*/
public class IfTest01
{
public static void main(String[] args){
// 需求:如果距离小于5公里,就去吃KFC
double distance = 1;
if (distance < 5)
{
System.out.println("我们去kfc,吃开封菜!!");
}
// 需求:
/* 成绩:成绩可能带有小数,且区间为[100-0]
[90-100] a
[80-90) b
[70-80) c
[60-70) d
[0-60) e
// 瑕疵编写方式
double score = 90;
if (score >= 90)
{
System.out.println('a');
}else if (score >= 80)
{
System.out.println('b');
}else if (score >= 70)
{
System.out.println('c');
}else if (score >= 60)
{
System.out.println('d');
}else{
System.out.println('e');
}
// 正确编写方式1
double score = 59.5;
score = -100;
if ( score < 0 | score > 100 )
{
System.out.println("该考生的成绩是不合法的!");
}else if ( score >= 90 )
{
System.out.println("该考生的成绩为A等级!");
}else if ( score >= 80 )
{
System.out.println("该考生的成绩为B等级!");
}else if ( score >= 70 )
{
System.out.println("该考生的成绩为C等级!");
}else if ( score >= 60 )
{
System.out.println("该考生的成绩为D等级!");
}else if ( score < 60 )
{
System.out.println("该考生的成绩为E等级!");
}
*/
// 方式2
double score = 59.5;
char q = 'c';
if ( score < 0 | score > 100 )
{
System.out.println("该考生的成绩是不合法的!");
}else if ( score >= 90 )
{
q = 'A';
}else if ( score >= 80 )
{
q = 'B';
}else if ( score >= 70 )
{
q = 'C';
}else if ( score >= 60 )
{
q = 'D';
}else if ( score < 60 )
{
q = 'E';
}
System.out.println("该考生的成绩为"+q+"等级!");
}
}
/*
需求:
年龄从键盘输入
年龄的每个阶段,要求年龄在[0-150]
[ 0-5 ] 幼儿
[ 6-10 ] 少年
[ 11 - 18 ] 青少年
[ 19 - 35 ] 青年
[ 36 - 55 ] 中年
[ 56 - 150 ] 老年
*/
public class IfTest02
{
public static void main(String[] args){
// 1、接收键盘输入:年龄【必须为数字】
java.util.Scanner s = new java.util.Scanner(System.in);
System.out.print("请输入测试人年龄:"); // 输入提示信息
int age = s.nextInt(); // 停下来等待用户输入,输入之后自动接收,赋值给age变量
System.out.println("测试人年龄为:"+age);
// 2、根据需求,进行业务逻辑判断
String str = "老年";
if ( age < 0 | age > 150 )
{
str = "您输入的年龄不合法,年龄应该在[1-150]之间";
}else if ( age >= 56 )
{
str = "老年";
}else if ( age >= 36 )
{
str = "中年";
}else if ( age >= 19 )
{
str = "青年";
}else if ( age >= 11 )
{
str = "青少年";
}else if ( age >= 6 )
{
str = "少年";
}else if ( age >= 0 )
{
str = "幼年";
}
System.out.println("您的年龄阶段为:"+str);
}
}
/* 判断当前的天气: 当外面下雨的时候: 带雨伞: 判断性别: 男士:带一把大黑伞 女士:带一把小花伞 当外面不下雨的时候: 判断外面温度: 当天气温度在30度以上: 判断性别: 男士:戴墨镜 女士:打遮阳伞 要求: 1、天气状况、温度、性别键盘键入;[weather temperature gender] 天气状况:1表示晴天、0表示雨天 温度直接使用数字表示 性别:1表示男,0表示女 2、要用嵌套*/public class IfTest03{ public static void main(String[] args){ // 创建键盘扫描对象 java.util.Scanner s = new java.util.Scanner(System.in); // 接收天气状况 System.out.print("请输入天气状况【雨天/晴天】:"); int weather = s.nextInt(); // 接收性别 System.out.print("请输入性别:"); int gender = s.nextInt(); if (weather == 0) { if (gender == 1) { System.out.println("下雨天男士带一把大黑伞"); }else if (gender == 0) { System.out.println("下雨天女士带一把小花伞"); }else{ System.out.println("您的性别是怎么回事?"); } }else if (weather == 1) { // 接收温度状况 System.out.print("请输入温度:"); int temperature = s.nextInt(); if (temperature >= 30){ if (gender == 1) { System.out.println("温度过高男士戴墨镜"); }else if(gender == 0) { System.out.println("温度过高女士抹防晒霜"); } } }else { System.out.println("您输入的天气状况不存在!!!"); } }}
/*
*/
public class IfTest04
{
public static void main(String[] args){
boolean gender = true;
/*编译错误:12行,else缺少if;12行以上没有语法错误
if (gender == false)
System.out.println("男1");
System.out.println("男2");
else
System.out.println("女");
if语句中没有加大括号,if语句中有一条Java语句
即上面的相当于
if (gender == false){
System.out.println("男1");
}
System.out.println("男2"); // 这条语句与if语句没有关系
else // else缺少if
System.out.println("女");
*/
}
}
/*1、for循环的语法结构: for(初始化表达式;布尔表达式;更新表达式){ 需要重复执行的代码片段【循环体】 }2、for循环的执行过程,执行原理 ***** 2.1初始化表达式、布尔表达式、更新表达式都不是必须的,但是两个分号是必须的 2.2初始化表达式最先执行,且仅仅执行一次 2.3布尔表达式的值只能是true或者false不能是其他值 2.4for循环执行原理:【逆时针旋转】 * 先执行初始化表达式,且仅执行一次 * 再执行布尔表达式: 布尔表达式为true 执行循环体 执行更新表达式 执行布尔表达式: 布尔表达式为true 执行循环体 执行更新表达式 布尔表达式为false 循环结束 布尔表达式为false 循环结束 3、循环结构: for... while... do...while... */public class ForTest01{ public static void main(String[] args){ // 输出1 ~ 10 十个数字 for (int j = 0; j <= 10; j += 1) // j = j + 1; j ++ { System.out.println("j----->" + j); } // 这里‘j’变量的作用域仅仅是整个for循环 for (int j = 0; j < 10; j ++) { System.out.println("j----->>" + j); } int j = 0; for (; j < 10; j++) { System.out.println("j=====>》" + j); // 输出0 ~ 9 } System.out.println("最后:" + j); // 10 }}
public class ForTest02{ public static void main(String[] args){ // 输出1~10中的奇数 for (int i = 1; i <= 10; i+=2) { System.out.println(i); } // 输出1~10中的偶数 for (int i = 2; i <= 10; i += 2) { System.out.println(i); } // for循环变形 for (int i = 1; i < 10; ) { System.out.println(i); // 1 2 3 4 5 6 7 8 9 i ++; } for (int i = 1; i < 10; ) { i ++; System.out.println(i); // 2 3 4 5 6 7 8 9 10 } }}
/*
循环语句,条件判断语句嵌套使用:
*/
public class ForTest03
{
public static void main(String[] args){
// 求1 ~ 100的奇数
// 第一种方案:
for (int i = 1; i <= 100; i += 2)
{
System.out.println(i);
}
// 第二种方案:
for (int i = 1; i <= 100; i ++)
{
if (i % 2 != 0) // 这个括号中加boolean类型
{
System.out.println(i);
}
}
}
}
// 求1 ~ 100所有奇数的和public class ForTest04{ public static void main(String[] args){ // 定义一个变量【盒子】存放累加的数据 int sum = 0; for (int i = 1; i <= 100; i += 2) { sum += i; } // for循环结束,输出累加的结果 System.out.println("sum = "+ sum); // 第二种方式: // 清零 sum = 0; for (int i = 1; i <= 100; i++) { if (i % 2 != 0) { sum += i; } } System.out.println("sum==>"+sum); }}
/* for循环的嵌套使用*/public class ForTest06{ public static void main(String[] args){ // for循环的嵌套使用【最终输出10个0 1 2】 for (int i = 1; i <= 10; i++) // 共循环10次 { // 这是循环体,无论是什么均需要执行10次 for (int j = 0; j <3; j++)// 共循环三次 { System.out.println(j); } } System.out.println("======================================="); for (int i = 0; i < 10; i++) // 循环10次【循环输出0 1 2 3三十次】 { for (int j = 0; j < 3; j++) // 循环3次 { System.out.println("Java程序员起步!!-->for循环"); for (int k = 0; k < 4; k++) // 循环4次输出0 1 2 3 { System.out.println("k==>"+k); } } } }}
/* for循环嵌套*/public class ForTest07{ public static void main(String[] args){ for (int i = 1; i <= 5; i++) { System.out.println("开始"+i); for (int j = 1; j <= 5; j++) { System.out.println(j+"-----"+(i * j)); } System.out.println("结束"); } }}
/* for循环嵌套: 输出9*9乘法表 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81# python实现99乘法表for i in range(1, 10): for j in range(1, i + 1): print("%d * %d = %d" % (i, j, i * j), end=" ") print("")*/public class ForTest08{ public static void main(String[] args){ for (int i = 1; i < 10; i++) { for (int j = 1; j < 10; j++) { System.out.println(i + "*" + j + "=" + (i*j)); } } /* 乘法表重复: 1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9 2*1=2 2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18 3*1=3 3*2=6 3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27 4*1=4 4*2=8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 */ System.out.println("======================================="); for (int i = 1; i < 10; i++) { for (int j = 1; j <= i; j++) { System.out.print(i + "*" + j + "=" + (i*j) + " "); } // 每一行输出结束换行 System.out.println(); // 换行 // System.out.println("\n"); // 换行【空一行】 } /* 运行结果: 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 */ }}
/*
编写for循环输出1 ~ 100 中的所有素数[可以被自身及1整除的数,不能被其他数整除的数]
2 3 5 7 9 11 13 17 ...
实现思路:
7 / 1【不需要】
7 / 2
7 / 3
7 / 4
7 / 5
7 / 6
7 / 7【不需要】
知识点:
for循环
for循环的嵌套
标记
break的使用
统计机制
*/
public class ForTest09
{
public static void main(String[] args){
/*
// 1既不是素数,也不是合数
for (int i = 2; i <= 1000; i++) // 外层for循环只负责取i值
{
boolean flag = true; // 默认将i看作素数【标记在开发中经常使用】
for (int j = 2; j < i; j++)
{
if (0 == i % j)
{
// 非素数
flag = false;
// 知道i不是素数,跳出循环,不加break效率低,一直往下除,直到除完为止
break;
}
}
if (flag)
{
System.out.print(i + " ");
}
// System.out.print(flag ? i + "是素数" : i + "不是素数" + " ");
}
*/
// 加入统计机制【每8个数字换一行】
/*
// 对8求余数的写法
int count = 0;
for (int i = 2; i <= 100; i++)
{
boolean flag = true;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
flag = false;
break;
}
}
if (flag)
{
System.out.print(i + " ");
count ++;
if (count % 8 == 0)
{
System.out.println();
}
}
}
*/
// 对count清零的写法
int count = 0;
for (int i = 2; i <= 100; i++)
{
boolean flag = true;
for (int j = 2; j < i; j++)
{
if (i % j == 0)
{
flag = false;
break;
}
}
if (flag)
{
System.out.print(i + " ");
count ++;
if (count == 8)
{
System.out.println();
count = 0; // 归零
}
}
}
}
}
/*
升级版:要求输出1 ~ 100之间的素数,每八个输出一行
*/
/* 1、while循环的语法结构 while (布尔表达式){ 循环体; } 2、while循环的执行原理 先判断布尔表达式的结果: 布尔表达式为true: 执行循环体; 判断布尔表达式的结果: 为true: 执行循环体; ... 为false: 循环结束; 布尔表达式为false: 循环结束; 3、while循环的循环次数 */// 关系运算符在运行期才会得出结果public class WhileTest01{ public static void main(String[] args){ // 编译通过 /* int i = 10; int j = 5; // 程序未运行,不知道i > j 是true还是false while (i > j) // 关系运算符在运行期才会得出结果 { System.out.println("死循环"); } System.out.println("编译通过,关系运算符,在运行阶段才会得出结果,因此没有报错!"); */ // 编译报错 /* while (true) { System.out.println("死循环"); } System.out.println("编译报错,因为这条语句永远无法执行!"); // 错误: 无法访问的语句 */ }}
/* while循环输出1~10*/public class WhileTest02{ public static void main(String[] args){ int i = 1; while (i <= 10) { System.out.println(i); // i += 1; // i ++; i = i + 1; } System.out.println("====>"+i); // 11 System.out.println("========================================================="); int j = 10; while (j >= 0) { System.out.println(--j); // 9 8 7 6 5 4 3 2 1 0 -1 System.out.println("===>"+j); // 9 8 7 6 5 4 3 2 1 0 -1 } System.out.println("---->>>>"+j); // -1 }}
/* do...while循环: 1、do...while循环的语法结构 do{ 循环体; }while(布尔表达式); // 最后有个分号,注意别丢了 2、do...while循环的执行原理 3、do...while循环的循环次数 * do...while循环的循环体至少循环一次【1~N次】 4、do...while循环的注意事项 * do...while循环最后有个分号,注意别丢了*/public class DoWhileTest01{ public static void main(String[] args){ int i = 10; do { System.out.println(i); } while (i > 100); // 输出10 System.out.println("====================================="); int j = 10; while (j > 100) { System.out.println(j); } // 没有输出 System.out.println("====================================="); int k = 1; do { System.out.println(k); // 1 2 3 4 5 6 7 8 9 10 k ++; } while (k <= 10); }}/* 总共三个循环语句: for while do...while*/
- break - continue
- 关键字- 字面值- 变量- 数据类型*** * 二进制 * 字符编码- 运算符- 控制语句*****- 方法***- 递归
耦合:就是事物与事物之间的相关程度 - 面向过程: 主要关注点是:具体的实现过程,因果关系【集成显卡的开发思路】 * 优点:对于业务逻辑简单的程序,可以达到快速开发,前期投入较低 * 缺点:采用面向过程的方式开发,很难解决非常复杂的业务逻辑 面向过程的开发过程导致软件元素之间的“耦合度”非常高,其中一环出 问题整个系统都会收到影响;导致最终的软件扩展力差。另外由于没有"独立体" 的概念,导致无法达到组件复用。 - 面向对象: 主要关注点是: 主要关注对象【独立体】能完成哪些功能【独立显卡的开发思路】 * 优点:耦合度低,扩展力强,更容易解决现实世界中复杂的业务逻辑,复用性强 * 缺点:前期投入成本较高,需要进行独立体的抽取,大量的系统分析和设计 - c 是纯面向过程的、c++半面向对象、Java纯面向对象 C#是面向对象的、Javascript是基于对象的语言。 - 新出现的语言都是面向对象的,人认识事物是以面向对象的方式 - 面向对象更符合人的思维方式
- 封装
- 继承
- 多态
所有面向对象得编程语言都有这三种特征
面向对象的方式开发一个软件,生命周期当中【整个生命周期当中贯穿使用OO面向对象方式】
- OOA面向对象的分析【analysis】
- OOD面向对象的设计【design】
- OOP面向对象的编程【programming】
什么是对象?
什么是类?
类—【实例化】–》对象
对象又被称为实例instance[实例]
对象—【抽象】–》类
/*
对象的创建和使用:
*/
public class OOTest01
{
public static void main(String[] args){
int i = 0;
// 通过一个类可以实例化N个对象
// 实例化对象的语法 new 类名();
// new是Java语言当中的运算符
// new运算符的作用是创建对象,在jvm的堆内存区中开辟新的内存空间
// 方法区内存:类加载的时候,.class字节码代码片段对被加载到该内存区
// 栈内存区【局部变量】:方法代码片段执行的时候,会给该方法分配分配内存空间,在栈内存中压栈。
// 堆内存区:new的对象在堆内存中存储
// Student是一个引用数据类型
// s是一个变量名
// new Student()是一个学生对象
// s是一个局部变量,在栈内存中存储
// 什么是对象?new运算符在堆内存中开辟出的内存空间,叫做对象
// 什么是引用?引用是一个变量,只不过这个变量保存了另一个Java对象的内存地址
// 不能直接操作堆内存,不像C语言,Java没有指针的概念,
// 要访问堆内存中的变量需要通过“引用”去访问堆内存中实例对象内部的实例变量
Student s = new Student();
// 访问实例变量的语法结构:
// 读取数据:引用.变量名;
// 修改数据:引用.变量名 = 值;
/*
// 读取数据:
int stuNum = s.num;
String stuName = s.name;
String stuAddress = s.address;
int stuAge = s.age;
boolean stuSex = s.sex;
System.out.println("学号:"+stuNum); // 0
System.out.println("姓名:"+stuName); // null
System.out.println("年龄:"+stuAge); // 0
System.out.println("性别:"+stuSex); // false
*/
System.out.println("学号:"+s.num); // 0
System.out.println("姓名:"+s.name); // null
System.out.println("年龄:"+s.age); // 0
System.out.println("性别:"+s.sex); // false
// 修改数据:
s.name = "jack";
s.age = 10;
s.num = 1527563998;
s.sex = true;
System.out.println("学号:"+s.num); // 0
System.out.println("姓名:"+s.name); // null
System.out.println("年龄:"+s.age); // 0
System.out.println("性别:"+s.sex); // false
// 在实例化一个对象
// Student 是数据类型
// stu 是引用,同时也是局部变量
// new Student() 是实例化的一个对象
Student stu = new Student();
// 编译报错
// 因为num是实例变量,对象级别的变量,存储在Java对象内部,必须先有对象才能访问
// 通过对象才能访问,不能通过“类名”访问
// System.out.println(Student.num);
}
}
/*
局部变量在jvm中的栈内存中存储
成员变量中的实例变量在堆内存中的Java对象内部存储
*/
// OOTest02.java
// 测试类
public class OOTest02
{
public static void main(String[] args){
// 实例化对象
User u = new User();
// 修改User对象内部实例化变量值
u.no = 110;
u.username = "jack"; // jack属于一个对象,属于String对象
u.addr = new Address();
// 得到一个User对象所在的城市
// 在main方法当中目前只能看到一个引用“u”
// 一切都只能是通过u来访问
System.out.println(u.username + "居住在这个城市:" + u.addr.city);
// 得到一个User对象住在哪个街道
System.out.println(u.username + "居住在这个街道:" + u.addr.street);
// 修改实例化变量的值
u.addr.city = "西安";
u.addr.street = "雁塔路";
u.addr.zipCode = 1111111;
System.out.println("城市:"+u.addr.city);
System.out.println("街道:"+u.addr.street);
System.out.println("邮编:"+u.addr.zipCode);
}
}
// User.java
// 用户类
public class User
{
// 属性【成员变量之实例变量】
// 用户编号
// 基本数据类型中的int
// no是一个实例变量
int no;
// 用户姓名
// 引用数据类型中的String
// username是一个实例变量,是一个引用
String username;
// 用户住址
// Address自定义的引用数据类型
// addr是一个实例变量,是一个引用
Address addr;
}
// OOTest03.java
public class OOTest03
{
public static void main(String[] args){
User u = new User();
// 上一个版本
// u.addr = new Address();
Address a = new Address();
u.addr = a;
System.out.println("a.city:"+a.city);
System.out.println("u.addr.city:"+u.addr.city);
a.city = "天津";
// u.addr.street = "长乐街";
System.out.println(a.city); // 天津
System.out.println(u.addr.city); // 天津
}
}
OOTest03.java
// OOTest04.java
public class OOTest04
{
public static void main(String[] args){
// 创建一个丈夫对象
Husband huangxiaoming = new Husband();
huangxiaoming.name = "黄晓明";
// 创建一个妻子对象
Wife yangying = new Wife();
yangying.name = "杨颖";
// 结婚【可以通过妻子找到丈夫,可以通过丈夫找到妻子】
huangxiaoming.w = yangying;
yangying.h = huangxiaoming;
System.out.println(huangxiaoming.w.name);
System.out.println(yangying.name); // 采用这种方式访问,说明不了,黄晓明和杨颖之间的福夫妻关系
}
}
// Husband.java
// 丈夫类:
public class Husband
{
// 姓名
String name;
// 丈夫对象中含有妻子引用
Wife w;
}
// Wife.java
// 妻子类:
public class Wife
{
// 姓名
String name;
// 妻子对象中含有丈夫引用
Husband h;
}
OOTest04.java
// OOTest05.java
// 测试程序
public class OOTest05
{
public static void main(String[] args){
Customer c = new Customer();
System.out.println(c.id); // 0
c = null;
// c = null地址置为null没有引用指向Customer对象,垃圾回收
// 编译不会报错,运行报错
// 空指针异常,空引用访问实例相关的数据,会发生空指针异常
// java.lang.NullPointerException
System.out.println(c.id);
}
}
// Customer.java
// Customer类
public class Customer
{
// id
int id;
}
// 测试程序【Student、Computer类的测试程序】
public class OOTest06
{
public static void main(String[] args){
// 创建对象
Student stu1 = new Student();
Computer c = new Computer();
// 学生和电脑建立关联关系
stu1.com = c;
System.out.println(stu1+"正在使用这台电脑:"+stu1.com);
}
}
// 计算机类
public class Computer
{
// 品牌
String brand;
// 型号
String model;
// 颜色
String color;
}
// Student是类,属于引用数据类型,这个类型名就是Student
// 不属于基本类型
// 学生类是一个模板
// 描述所有学生的共同特征【属性+方法】
public class Student
{
// 属性【描述的对象的状态信息】
// 属性通常使用变量定义
// 类体中,方法体之外的变量,称为“成员变量”
// 成员变量没有赋值,系统默认赋值,一切向“0”看齐
// 所有学生都有学号
// 每个学生的学号不同
// 要访问学生的学号,需要先创建对象,通过对象去访问学生的学号信息,
// 学号信息不能直接通过“类”去访问,只能通过“实例化的对象”访问,所以这种“成员变量”又叫做
// “实例变量”,对象又被称作实例,实例变量又被称作:对象变量,【对象级别的变量】
// 不创建对象name变量的内存空间是不存在的,只有创建了对象这个name变量的空间才会创建
// 姓名
String name;
// 学号
int num;
// 年龄
int age;
// 地址
String address;
// 性别
boolean sex;
// 方法【描述的是对象的动作信息】
// 学生有笔记本电脑
Computer com;
}
// 测试程序
public class OOTest07
{
public static void main(String[] args){
// 创建人类
Ren jinChen = new Ren();
// 不采用系统默认赋值
// 手动赋值
jinChen.name = "靳晨";
jinChen.age = 100;
jinChen.id = 12345678;
jinChen.sex = false;
// 创建House类
House h = new House();
// 建立房子和人的关系
h.houseHolder = jinChen;
// 输出房子主人的名字
System.out.println("房子主人的名字:" + h.houseHolder.name);
// 房子易主了,重新创建一个人的对象
Ren liSi = new Ren();
// 自定义liSi对象的属性
liSi.name = "李四";
liSi.age = 120;
liSi.id = 119116;
// 建立房子和新主人的关系
h.houseHolder = liSi;
// 输出房子新主人的名字,年龄
System.out.println("名字、年龄" + h.houseHolder.name+" " + h.houseHolder.age);
// 输出房子的主人的身份证号;
System.out.println("房子的主人的身份证号:"+ h.houseHolder.id);
}
}
// 人类
public class Ren
{
// 姓名
String name;
// 身份证号
int id;
// 年龄
int age;
// 性别
boolean sex;
}
// House类
public class House
{
// 面积
double area;
// 主人
Ren houseHolder;
}
// 在一个文件中
public class OOTest08
{
public static void main(String[] args){
// 创建对象
Student stu1 = new Student();
stu1.no = 12345;
stu1.name = "小李";
// 创建对象
Computer com = new Computer();
com.brand = "logitech";
com.color = "灰色";
// 建立学生和电脑之间得关系
stu1.com1 = com;
// 输出学生电脑得品牌
System.out.println("学生电脑的品牌:" + stu1.com1.brand);
// 学生1换电脑了
stu1.com1 = new Computer();
// 输出换的新电脑的品牌
System.out.println(stu1.com1.brand); // null
// 因为换的新电脑没有赋值,是默认值
}
}
class Computer
{
// 品牌
String brand;
// 颜色
String color;
// 型号
int model;
}
class Student
{
// 姓名
String name;
// 学号
int no;
// 有电脑
// Student是一个类,Computer是一个类如何让两个类之间产生关系
// 在学生类中有Computer com1这个属性
Computer com1;
}
* 类的语法结构:
[修饰符列表] class 类名 {
状态【属性】;
动作【方法】;
}
* 学生类,描述学生的共同特征:
状态信息:
姓名
学号
身份证号
年龄
身高
体重
动作信息:
吃饭
睡觉
学习
玩
唱歌
跳舞
...
/*
2021/3/20
抽象类:
1、什么是抽象类?
类和类之间有共同特征,把这些共同特征提取出来,形成的就是抽象类
2、抽象类是什么类型?
抽象类也属于引用数据类型
3、定义抽象类?
语法:
[修饰符列表] class abstract 类名{
类体;
}
4、抽象类无法实例化,无法创建对象,所以抽象类是用来被子类继承的
5、final和abstract不能联合使用,这两个关键字是对立的。
6、抽象类的子类可以是抽象类
7、抽象类无法实例化对象,但是抽象类有构造方法,这个构造方法是供子类使用的。
子类的对象在创建的时候,它先去调用父类的构造方法
8、抽象类关联到一个概念:抽象方法,抽象方法是没有实现的方法,没有方法体的方法
public abstract void doSome();
抽象方法的特点:
特点一:没有方法体,以分号结尾
特点二:前面修饰符列表中有abstract关键字修饰
9、抽象类中不一定有抽象方法,可以有普通方法。抽象方法必须在抽象类中。
*/
public class AbstractTest01
{
public static void main(String[] args){
// 错误: Account是抽象的; 无法实例化
// Account a = new Account();
}
}
// 银行账户类
abstract class Account
{
// 普通方法
public void withdraw(){
}
// 抽象方法
public abstract void doSome();
}
// 抽象类的子类
// 信用卡类
// 抽象类无法创建对象,无法实例化,是用来被继承的
// 子类可以实例化对象,可以创建对象
/*
class CreditCard extends Account
{
}
*/
// 抽象类的子类可以是抽象类吗?可以
abstract class CreditCard extends Account
{
}
/*
非抽象类继承抽象方法,必须将抽象方法实现
*/
public class AbstractTest02
{
public static void main(String[] args){
}
}
// 动物类(抽象类)
abstract class Animal
{
// 抽象方法
public abstract void move();
}
// 子类(非抽象类)
class Bird extends Animal
{
// 需要将从父类中继承过来的抽象方法重写/覆盖。或者也可以叫做实现。
// 把抽象的方法实现了
}
/* 程序不使用方法: 代码未重复使用,只不过是相同的代码写了三遍[只不过没次参与求和的数据不同] Java语言当中应该有这样的机制 - 实现某个功能的代码只需要写一遍 - 实现这个功能只需要输入数字即可,就可以得到结果 这样代码就可以重复利用了,提高代码的复用性【这就是方法】 - 使用这个方法,称为调用,即“invoke”,*/public class MethodTest01{ public static void main(String[] args){ // 需求1:求两个int类型数字的和 int a = 100; int b = 100; int sum = a + b; System.out.println(a + "+" + b + "=" + sum); // 需求1:求两个int类型数字的和 int z = 110; int x = 119; int q = z + x; System.out.println(z + "+" + x + "=" + q); // 需求1:求两个int类型数字的和 int y = 114; int u = 120; int i = y + u; System.out.println(y + "+" + u + "=" + i); }}
/*
以下程序使用方法这种机制
- 方法Method在c语言当中叫做函数\Function
- 方法定义在类体当中,一个类中可以定义多个方法,方法编写的位置没有先后顺序,可以随意。
- 方法体当中不能再定义方法
- 方法体当中的代码有先后顺序,执行自上而下依次执行
*/
public class MethodTest02
{
public static void main(String[] args){
// 调用定义的方法求和
MethodTest02.sumInt(10, 20);
}
// 定义方法
public static void sumInt(int a, int b){
int c = a + b;
System.out.println(a + "+" + b + "=" + c);
}
}
/*
关于Java语言当中的方法:
1、定义方法,语法结构:
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
2、方法语法结构解释:
2.1 修饰符列表:
- 目前写成:"public static"
- 可选项,不是必须的
- 方法的修饰符列表中有static关键字,如何调用这个方法
类名.方法名(实际参数列表)
2.2 返回值:
- 一个方法执行完成之后,返回最终执行结果,即会有某种类型的“数据”返回,这个“数据”就是返回值
- 返回值的类型可以是Java语言当中的任意一种类型,也可以是引用数据类型
byte short int long float double boolean char String void 等
- 不是每个方法都需要有返回值,有可能这种方法执行完成之后不返回任何类型数据,
但是,返回值类型位置必须编写:void 关键字
- 指定的返回值不是void,则方法执行完成必须返回一个具体的该类型的数据
否则编译器报错,只能是指定类型的数据
- 如何编写返回值?
return 值;
并且返回值的数据类型必须和方法中的返回值的数据类型一致,否则编译器报错。
- 返回值类型是void,不能在方法体中编写return语句,但是,注意!可以编写“return;”这样的
语句
- 只要return语句执行,return所在的方法执行结束【注意不是jvm结束,是return所在的方法结束】
2.3 形式参数列表【形参】
- 形参是局部变量
- 多个形参之间用逗号隔开
- 形参的个数 0 ~ N 个
- 形参中起决定作用的是形参的数据类型,形参的名字就是局部变量的名字
- 形参列表和实参列表必须保持数量相同,类型对应相同
2.4 方法如何调用?
- 方法只定义不调用,方法不会执行
- 语法规则:方法的修饰符列表中有“static”的
类名.方法名(实参列表); <这是一条Java语句,表示调用某个类的某个方法,传递这样的实参>
*/
public class MethodTest03
{
public static void main(String[] args){ // 这里的void是:"空白"的意思,即未指定返回值类型
}
/*
public static 返回值类型 方法名(形参列表){ // “public static” :是修饰符列表
}
*/
}
// public 公开的// class 类// MethodTest04 方法名public class MethodTest04 // 表示定义一个公开的类,类名为MethodTest04,由于是公开的类,所以源文件名必须是:MethodTest04.java{ // 类体 // 类体中不能直接编写Java语句,除声明变量外 // 方法出现在类体中 // 方法 // public 公开的 // static 静态的 // void 表示方法执行结束之后不返回任何数据 // main是方法名:主方法 // (String[] args)形式参数列表,其中:String[]引用数据类型 ,args局部变量的变量名 // 所以以下只有args可以随意编写 // 主方法就是这样编写的,这是程序的入口,固定编写方式【SUN公司规定的】 public static void main(String[] args){ // 这里的程序一定会执行 // Java虚拟机负责调用主方法,是一个程序的入口位置 // 从这里开始执行程序 MethodTest04.sum(10, 20);// [实际上执行到这里main方法暂停,进入到sum方法执行,sum执行结束,main方法的这一行执行结束] // 一个方法可以被重复调用 int a = 100; MethodTest04.sum(a, 500); } // 自定义方法 // 不是程序的入口 // 方法作用:输出两个int类型变量的和,不返回结果,但是要求直接将结果输出到控制台 public static void sum(int x, int y){ System.out.println(x + "+" + y + "=" + (x + y)); }}
/* 方法的调用不一定要在main方法当中 只要程序可以执行到这里都可以在该位置调用*/public class MethodTest05{ public static void main(String[] args){ // 调用sum方法 MethodTest05.sum(10, 110); System.out.println("Hello World!!"); } public static void sum(int x, int y){ System.out.println(x + "+" + y + "=" + (x + y)); // 调用dosome方法 MethodTest05.doSome(); } public static void doSome(){ System.out.println("doSome!"); }}
public class MethodTest06
{
public static void main(String[] args){
// 对于所定义方法的修饰符列表中有static的方法
// 可以省略"类名."来调用方法
MethodTest06.doSome(); // 完整的方式
doSome(); // 省略的方式
// 调用其他类中【不是本类中】的方法
A.doOther();
}
public static void doSome(){
System.out.println("doSome!!!");
}
}
class A
{
public static void doOther(){
System.out.println("doOther!!!");
}
}
public class MethodTest07{ public static void main(String[] args){ division(10, 2); // 这里没有接收这个方法的返回值 // 使用变量接收这个方法执行结束之后的返回值 // 变量的数据类型需要和返回值的数据类型相同,也可以自动类型转换。 int d = division(10, 3); System.out.println(d); System.out.println(division(10, 3)); // 直接输出 } // 定义一个方法:要求计算两个int类型变量的商, // 并将结果返回给调用者 public static int division(int a, int b){ /* int c = a / b; return c; */ return a / b; }}
/* 深入理解return语句: * 带有return关键字的Java语句如果执行,所在的方法执行结束 * 在"同一个作用域当中",return语句下面不能有任何代码,因为这些代码永远都执行不到, 因此会报错*/public class MethodTest08{ public static void main(String[] args){ int b = MethodTest08.m(); System.out.println(b); } /* // 编译器认为无法保证100%"return 1;"会执行; // 以下语句编译报错:因为a > 3 编译阶段不知道是true还是false有可能没有返回值 // 而指定了自定义类的返回值数据类型(必须有返回值),因此报错 public static int m(){ int a = 10; if (a > 3) { return 1; } }// 错误: 缺少返回语句 */ /* // 修改以上编译报错程序 public static int m() { int a = 10; if (a > 3) { return 1; }else{ return 0; } } */ /* // 以下代码等同于以上代码 public static int m() { int a = 10; if (a > 3) { return 1; // 这条语句执行,以下语句不再执行 // System.out.println("HelloWorld!!"); // 编译报错 错误: 无法访问的语句 } System.out.println("HelloWorld!!"); // 没有问题!!跳出了第一个return所在的作用域 return 0; // System.out.println("HelloWorld!!"); // 编译报错,无法访问的语句 } */ // 替代上面的冗余代码 public static int m(){ return 10 > 3 ? 1 : 0; }}
/* 在返回值类型是void的语句中使用return语句: return语句出现在返回值类型是void的方法当中主要是为了终止程序的执行*/public class MethodTest09{ public static void main(String[] args) { // System.out.println(m()); m(); } /* public static void m() { // return 10; // 编译报错,错误: 不兼容的类型: 意外的返回值 return; } */ public static void m(){ for (int i = 1; i <= 10; i ++){ if (i == 5){ // return; // 终止整个方法 最终不会输出"Hello World!!!" break; // 终止for循环 最终还会输出"Hello World!!!" } System.out.println("i---->"+i); } System.out.println("Hello World!!!"); }}
/* 方法在执行过程中,在jvm中是如何分配的,是如何变化的? 1、方法只定义,不调用是不会执行的,并且在jvm中也不会分配“运行所属”的内存空间。 只有在调用的时候才会分配运行所属的内存空间。 2、在jvm内存划分上有三块主要的内存区域【当然除了这三块,还有其他的内存区域】: * 方法区内存 * 堆内存 * 栈内存 3、关于栈数据结构: * 栈:stack,是一种数据结构 * 数据结构是一种数据存储的形态 * 数据结构是一门独立的学科,不属于任何语言的范畴,只不过在大多数编程语言中会使用到 * 常见的数据结构: - 数组 - 队列 - 栈 - 二叉树 - 链表 - 栈 - 哈希表\散列表 ... 4、方法代码片段存在哪里?方法执行过程中,从哪里分配内存? * 方法代码片段属于.class字节码文件的一部分,字节码文件在类加载的时候, 将其放在了方法区当中所以jvm中三块主要的内存空间中,方法区内存最先有数据。 存放了代码片段 * 代码片段虽然在方法区内存中只有一份,但是可以被重复调用。 每一次调用这个方法的时候,需要给该方法分配独立的活动场所, 这个活动场所在栈内存空间中分配 5、方法在调用的时候,会给该方法分配独立的内存空间,在栈中分配,此时发生压栈的动作 方法执行结束之后,发生弹栈的动作,给该方法分配的栈内存空间释放。 压栈:给该方法分配内存 弹栈:释放为该方法分配的内存空间 6、局部变量在方法体中声明,局部变量在运行阶段,内存在栈中分配。 7、注意:方法调用的时候,在参数传递的时候,实际上传递的是变量中保存的值 */public class MethodTest10{ public static void main(String[] args){ }}
/*
方法执行过程中的内存分析:
1、局部变量在方法体中声明,局部变量在运行阶段,内存在栈中分配。
2、注意:方法调用的时候,在参数传递的时候,实际上传递的是变量中保存的值
*/
public class MethodTest11
{
// 画图分析
public static void main(String[] args){
int i = 10;
method(i);
System.out.println("main--->"+i); // 10
}
public static void method(int i){
i ++;
System.out.println("method--->"+i); // 11
}
}
/*
方法的重载机制:
以下程序不使用方法重载机制:
缺点:
1、三个不同的方法虽然实现的功能不同,但都是求和的,且相似,功能相似的三个方法分别起了不同的
方法名,对程序员来说需要记忆三个不同的方法名,才能完成调用【不方便】
2、不美观
方法的重载机制,解决了这些问题
*/
public class OverloadTest01
{
public static void main(String[] args){
// 调用方法
int result1 = sumInt(1, 2);
System.out.println(result1);
double result2 = sumDouble(1.0, 2.0);
System.out.println(result1);
long result3 = sumLong(1L, 2L);
System.out.println(result1);
}
// 定义一个方法,可以计算两个int类型数据的和
public static int sumInt(int a, int b){
return a + b;
}
// 定义一个方法,可以计算两个double类型数据的和
public static double sumDouble(double a, double b){
return a + b;
}
// 定义一个方法,可以计算两个long类型数据的和
public static long sumLong(long a, long b){
return a + b;
}
}
/*
方法重载的使用:
前提是:功能相似的时候
*/
public class OverloadTest02
{
public static void main(String[] args){
//调用不同的方法的时候就像使用同一个方法一样
// 参数的类型不同对应调用不同的方法,调用方法不再依靠方法名了,依靠的是参数的类型不同
// 不同的参数类型对应调用不同的方法
System.out.println(sum(1, 2));
System.out.println(sum(1.0, 2.0));
System.out.println(sum(1L, 2L));
}
// 以下程序使用方法重载机制
public static int sum(int a, int b){
System.out.println("intSum");
return a + b;
}
public static long sum(long a, long b){
System.out.println("longSum");
return a + b;
}
public static double sum(double a, double b){
System.out.println("doubleSum");
return a + b;
}
}
/*
方法重载:
1、方法重载又叫做:overload
2、什么时候使用方法重载?
方法功能相似的时候,尽可能让方法名相同
3、什么条件满足的情况下构成方法重载?
- 同一个类当中
- 方法名不同
- 参数列表不同
* 参数类型不同
* 参数数量不同
* 参数类型顺序不同
4、方法重载和什么有关系?和什么没有关系?
***- 方法重载只和方法名+参数类型有关
- 方法重载和返回值类型无关
- 方法重载和修饰符列表无关
*/
public class OverloadTest03
{
public static void main(String[] args){
m1();
m1(10);
m2(2.0, 1);
m2(1, 2.0);
m3(11L);
m3(10);
}
// 同一个类中,方法名一样,参数列表不同
// 以下两个方法构成重载[参数列表数量不同]
public static void m1(){}
public static void m1(int a){}
// 以下两个方法构成重载[参数列表顺序不同]
public static void m2(double a, int b){}
public static void m2(int a, double b){}
// 以下两个方法构成重载[参数列表类型不同]
public static void m3(long b){}
public static void m3(int a){}
// 以下两个方法不是方法重载是发生方法重复了;
// 方法重载调用不同的方法起决定性作用的是参数类型,不是参数名
/*
public static void m4(int a, int b){}
public static void m4(int b, int a){}
*/
// 方法重载和返回值类型没有关系
// 以下程序编译报错
// 错误: 已在类 OverloadTest03中定义了方法 m5()
/*
public static void m5(){}
public static int m5(){
return 1;
}
*/
// 编译报错
// 方法重载和修饰符列表无关
/*
void m6(){}
public static void m6(){}
*/
}
/*
方法重载的应用
*/
public class OverloadTest04
{
public static void main(String[] args){
U.p(10);
U.p("哈哈哈");
U.p('a');
U.p(false);
}
}
// 将U这个公开的类放在一个文件内
public class U
{
public static void p(int a){
System.out.println(a);
}
public static void p(byte a){
System.out.println(a);
}
public static void p(short a){
System.out.println(a);
}
public static void p(long a){
System.out.println(a);
}
public static void p(double a){
System.out.println(a);
}
public static void p(boolean a){
System.out.println(a);
}
public static void p(char a){
System.out.println(a);
}
public static void p(String a){
System.out.println(a);
}
}
/* 关于方法的递归调用: 1、什么是递归调用? 方法自身调用自身 2、递归算法是很耗费栈内存的,递归可以不用的时候尽量不用 3、以下程序运行发生一个错误【不是异常】 以下错误无法挽回,一个结果:jvm停止工作 Exception in thread "main" java.lang.StackOverflowError 栈内存溢出错误 4、递归必须有一个结束条件,否则必定发生栈内存的溢出错误 5、递归即使有正确的结束条件,依然有可能发生栈内存溢出错误,因为递归的太深了*/public class RecursionTest01{ public static void main(String[] args){ System.out.println("main begin"); doSome(); // 这行代码不结束,下一行代码是不会执行的 System.out.println("main over"); // 不会执行 } public static void doSome(){ // System.out.println("doSome begin"); doSome(); // 这行代码不结束,下一行代码是不会执行的 // System.out.println("doSome over"); // 不会执行 }}
/* 不使用递归计算1~N的求和*/public class RecursionTest02{ public static void main(String[] args){ // 求1~4的和 /* int result = 0; for (int i = 1;; i++) { result += i; } System.out.println(result); */ // 直接调用方法即可 int retresult = sumInt(10); System.out.println(retresult); retresult = sumInt(20); System.out.println(retresult); } // 单独定义一个方法,求1~n的和 public static int sumInt(int n){ int result = 0; for (int i = 1; i < n; i++) { result += i; } return result; }}
/* 使用递归计算1~4的和 1 + 2 + 3 + 4 4 + 3 + 2 + 1 <---- n + (n - 1) + (n - 1 - 1)...*/public class RecursionTest03{ public static void main(String[] args){ int n = 4; int retValue = sum(n); System.out.println(retValue); } public static int sum(int n){ // 4 + 3 + 2 + 1 if (n == 1) { return 1; // 返回给下面的sum(2 - 1),是sum(2 - 1)调用的n == 1因此返回给它 } return n + sum(n - 1); }}/*n + sum(n - 1)4 + sum(3)4 + 3 + sum(2)4 + 3 + 2 + sum(1)4 + 3 + 2 + 1*/
/* 不使用递归计算N的阶乘: 5的阶乘: 5 * 4 * 3 * 2 * 1*//*public class RecursionTest04{ public static void main(String[] args){ int n = 5; int retresult = factorial(n); System.out.println(retresult); } public static int factorial(int n){ int result = 1; for (int i = n; i > 0; i--) { result *= i; } return result; }}// 递归方式:public class RecursionTest04{ public static void main(String[] args){ int n = 5; int retresult = factorial(n); System.out.println(retresult); } public static int factorial(int n){ if (n == 1) { return 1; } return n * factorial(n - 1); }}*/
object类中的toString()方法
/*1、SUN公司设计toString()方法的目的是什么? 通过调用这个方法可以将Java对象转换成字符串2、建议重写toString()方法 */public class Test01{ public static void main(String[] args){ // 通过有参构造方法创建对象 MyTime t1 = new MyTime(1998,12,16); // 调用toString()方法,返回值输出 String s1 = t1.toString(); System.out.println(s1); // 1998年12月16日 //直接调用toString()方法 System.out.println(t1.toString()); // 1998年12月16日 // 注意:输出引用的时候会自动调用引用的toString()方法 System.out.println(t1); // 1998年12月16日 }}class MyTime{ int year; int month; int day; public MyTime(){ } public MyTime(int year, int month, int day){ this.year = year; this.month = month; this.day = day; } // 重写toString()方法 public String toString(){ return this.year + "年" + this.month + "月" + this.day + "日"; }}
object类中的equals()方法
注意⚠️,Java中“==”判断的是两个对象的内存地址是否相等;equals()方法判断的是两个java对象是否相等。
/*
关于Object类中的equals()方法:
1、源代码:
public boolean equals(Object obj) {
return this == obj;
}
以上这个方法是Object类的默认实现
2、SUN公司设equals()这个方法的目的是什么?
以后编程过程中都要通过equals()方法判断两个对象是否相等
判断两个Java对象是否相等
3、判断两个Java对象是否相等不能使用“==”,因为“==”比较的是两个对象的内存地址
4、Object类中的equals方法够用吗?
不够,因为其返回的是“==”
在Object类中判断两个Java对象是否相等,默认使用的“==”判断两个Java对象是否相等。
而“==”判断的是两个Java对象的内存地址是否相等,所以Object类的equals方法,不够用
需要子类重写equals()方法
*/
public class Test02
{
public static void main(String[] args){
// 判断两个基本数据类型是否相等,使用“==”
int a = 100;
int b = 100;
System.out.println(a == b); // true
// 判断两个Java对象是否相等
// 创建MyTime对象
MyTime t1 = new MyTime(1998,12,16);
// 创建一个新的MyTime对象
MyTime t2 = new MyTime(1998,12,16);
// 测试使用“==”判断两个Java对象
// t1 和 t2中保存的内存地址不一样,而“==”比较的是内存地址
System.out.println(t1 == t2); // false
// 重写equals方法之前(比较的是内存地址)
// boolean flag = t1.equals(t2);
// System.out.println(flag); // false
// 重写equals方法之后(比较的是内容)
boolean flag = t1.equals(t2);
// 两个日期相等就是true
System.out.println(flag); // true
// 再创建一个对象
MyTime t3 = new MyTime(1998,12,26);
// 两个日期不相等就是false
System.out.println(t1.equals(t3)); // false
// 这个程序有bug吗?效率怎么样?低(如何改造)
MyTime t4 = null;
System.out.println(t1.equals(t4)); // false
}
}
class MyTime
{
// 属性
int year;
int month;
int day;
// 构造方法
public MyTime(){
}
public MyTime(int year, int month, int day){
this.year = year;
this.month = month;
this.day = day;
}
// 重写equals方法
// 怎么重写:相同的返回值类型,相同的方法名,相同的形式参数列表
/*
public boolean equals(Object obj){
// 获取第一个日期的年月日(这里的this指的是t1,因为是t1调用的equals()方法,传进来的参数形参obj对应的是t2这个实参)
int year1 = this.year;
int month1 = this.month;
int day1 = this.day;
// 获取第二个日期的年月日
if (obj instanceof MyTime)// instanceof它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
{
MyTime t = (MyTime)obj; // 向下转型,强制类型转换
int year2 = t.year;
int month2 = t.month;
int day2 = t.day;
if (year1 == year2 && month1 == month2 && day1 == day2)
{
return true;
}
}
return false;
}
*/
/*
// 改良equals方法
public boolean equals(Object obj){
// 如果obj是空直接返回false
if (obj == null)
{
return false;
}
// 如果obj不是MyTime引用类型,直接返回false
if (! (obj instanceof MyTime))
{
return false;
}
// 意思是this和obj的内存地址相同
// 内存地址相同指向的堆内存中的对象相同,是同一个
if (this == obj)
{
return true;
}
// 程序执行到此处,说明obj不是null是MyTime类型
// 可以进行向下转型
MyTime t = (MyTime)obj; // 向下转型,强制类型转换
if (this.year == t.year && this.month == t.month && this.day == t.day)
{
return true;
}
return false;
}
*/
/*
// 再次改良
public boolean equals(Object obj){
// 如果obj是空直接返回false
if (obj == null)
{
return false;
}
// 如果obj不是MyTime引用类型,直接返回false
if (! (obj instanceof MyTime))
{
return false;
}
// 意思是this和obj的内存地址相同
// 内存地址相同指向的堆内存中的对象相同,是同一个
if (this == obj)
{
return true;
}
// 程序执行到此处,说明obj不是null是MyTime类型
// 可以进行向下转型
MyTime t = (MyTime)obj; // 向下转型,强制类型转换
return this.year == t.year && this.month == t.month && this.day == t.day;
// && 短路与,相等就是true,不相等就是false
}
*/
public boolean equals(Object obj){
if (obj == null || ! (obj instanceof MyTime))
{
return false;
}
if (this == obj)
{
return true;
}
// 可以进行向下转型,强制类型转换 (obj是Object类型,里面没有MyTime02中的属性,需要转成MyTime02
// 里面才有需要的属性)
MyTime t = (MyTime) obj; // 向下转型,强制类型转换
return this.year == t.year && this.month == t.month && this.day == t.day;
}
}
toString和equals
/* java语言当中的String有没有重写toString方法,和equals方法? 只要是类就有构造方法,只要是类就有equals方法,只要是类就有toString方法 总结: 1、String类已经重写了equals方法,比较两个字符串不能使用“==”, 必须使用equals方法,equals是通用的。 2、String类重写了toString方法*/public class Test03{ public static void main(String[] args){ // 大部分情况下使用这种方式创建字符串对象 String s1 = "hello"; String s2 = "abc"; // String实际上也是一个类,既然是类就存在构造方法 String s3 = new String("Test01"); String s4 = new String("Test01"); // new两次,两个内存地址,s3的内存地址和s4的内存地址不相同 // System.out.println(s3 == s4); // false // “==”判断的是内存地址,不是内容 // 比较两个字符串能否使用“==”? // 不能,“==”比较的是两个对象的内存地址 System.out.println(s3.equals(s4)); // true // String类有没有重写toString方法 // 重写了toString方法 String s5 = new String("超级无敌"); // 没有重写toString方法,输出结果:java.lang.String@十六进制位的地址 // 经过测试,已经重写了toString方法 System.out.println(s5.toString()); // 超级无敌 System.out.println(s5); // 当输出引用的时候,会自动调用这个引用的toString方法 }}
示例1:重写equals()方法
public class Test04
{
public static void main(String[] args){
// 创建对象
Student s2 = new Student(2008811566, "实验幼儿园");
Student s3 = new Student(2008811566, "实验幼儿园");
System.out.println(s2.equals(s3)); // true
}
}
class Student
{
int no;
String school;
// 构造方法
public Student(){
}
public Student(int no, String school){
this.no = no;
this.school = school;
}
// 重写toString方法
public String toString(){
return "学号:" + no + ", 学校:" + school;
}
// 重写equals方法
// 需求:当一个学生的学号,学校相同时,代表同一个学生
public boolean equals(Object o){
if (o == null || ! (o instanceof Student)){
return false;
}
if (this == o){
return true;
}
Student s1 = (Student)o; // 向下转型,强制类型转换
/*if (this.no == s1.no && this.school.equals(s1.school)){
return true;
}*/
return this.no == s1.no && this.school.equals(s1.school);
return false;
}
}
示例2:重写equals()方法
public class Test05
{
public static void main(String[] args){
User u1 = new User("zhangsan", new Address(1111, "西安", "雁塔路,55号"));
User u2 = new User("zhangsan", new Address(1111, "西安", "雁塔路,55号"));
System.out.println(u1 == u2); // false
System.out.println(u1.equals(u2)); // true
}
}
class User
{
String name;
Address addr;
public User(){}
public User(String name, Address addr){
this.name = name;
this.addr = addr;
}
// 重写equals方法
public boolean equals(Object obj){
if (obj == null || !(obj instanceof User))return false;
if (obj == this)return true;
User u = (User)obj;
/*
obj是Object类型,里面没有name,addr属性,需要对其进行转型
转成User类型,里面才有需要的属性
*/
return this.name.equals(u.name) && this.addr.equals(u.addr);
// 后面的调用Address的equals方法,因此需要重写Address里的equals方法
}
}
class Address
{
int zipCode;
String city;
String street;
public Address(){}
public Address(int zipCode, String city, String street){
this.zipCode = zipCode;
this.city = city;
this.street = street;
}
// 重写equals方法
public boolean equals(Object obj){
if (obj == null || ! (obj instanceof Address))return false;
if (obj == this)return true;
Address a = (Address)obj;
return a.zipCode == this.zipCode && a.city.equals(this.city) && a.street.equals(this.street);
// 这里调用的String里的equals方法
}
}
object类中的finalize方法:
/*关于Object类中的finalize方法: 1、finalize()方法在Object类中的源代码: @Deprecated(since="9") // deprecated表示这个方法已经过时 protected void finalize() throws Throwable { } 2、这个方法不需要程序员来调用,jvm中的垃圾回收器会调用 不像equals() toString() 需要程序员自己调用,finalize()方法会在相应时机自动调用(GC调用) 3、finalize()方法的调用时机? 当一个Java对象即将被垃圾回收器回收掉时,垃圾回收器负责调用finalize()方法 4、finalize方法是SUN公司位Java程序员准备的一个时机,一个垃圾销毁时机, 如果希望在垃圾销毁时机执行一段代码,把这段代码放进finalize方法体中即可。 5、静态代码块的作用? static { ... } 静态代码块在类加载时机执行,且只执行一次 这是SUN公司准备的类加载时机 finalize()方法也是SUN准备的一个时机 这个时机是垃圾回收时机。 6、Java中的垃圾回收器不是轻易启动的, 时间没到,垃圾太少,种种条件下, 有可能启动也有可能不启动。*/public class Test06{ public static void main(String[] args){ /*Person p = new Person(); p = null;*/ // 多造点垃圾让他回收 for (int i = 0; i < 1000000 ; i++) { Person p = new Person(); p = null; } }}// 项目开发过程中有这样的需求:所有对象在jvm中被释放的时候,记录一下释放的时间class Person{ // 重写finalize方法 // Person对象被垃圾回收器回收的时候,垃圾回收器负责调用 protected void finalize() throws Throwable { System.out.println(this + "即将要被回收掉了,是GC调用的!!"); }}
Object类中的hashCode()方法:
/*hashCode()方法: 1、源码: public native int hashCode(); 带有native关键字,底层调用C++程序,不是抽象方法 2、hashCode()返回的是哈希码 实际上就是一个Java对象的内存地址,经过哈希算法,得出的一个值 所以hashCode()方法的执行结果可以等同看作,Java对象的内存地址*/public class Test07{ public static void main(String[] args){ Object o = new Object(); int hashCodeValue = o.hashCode(); System.out.println(hashCodeValue); // 对象内存地址通过哈希算法转换得到的一个值,可以等同看作内存地址 }}
/* 关于Java语言当中的运算符之:算数运算符 + 求和 - 相减 * 乘 / 商 % 求余数【取模】 ++ 自加1 -- 自减1 注意:一个表达式中有多个运算符,运算符有优先级,不确定时加小括号,优先级得到提升。 */public class OperaterTest01{ public static void main(String[] args){ int i = 10; int j = 3; System.out.println(i + j); // 10 System.out.println(i - j); // 7 System.out.println(i * j); // 30 System.out.println(i / j); // 3 System.out.println(i % j); // 1 // 小结:++ 可以放在变量前,也可以放在变量后,只要运算结束,该变量必定自加1操作 // ++ 放在变量后,先进行赋值运算,赋值运算结束,再进行++运算。 int a = 100; int b = a ++; System.out.println(a); // 101 System.out.println(b); // 100 // ++ 出现在变量之前 // 规则:先进行自加1运算,再进行赋值运算 int m = 20; int n = ++ m; System.out.println(m); // 21 System.out.println(n); // 21 int mm = 100; System.out.println(mm++); // 100 System.out.println(mm); // 101 int s = 50; System.out.println(++s); // 51 System.out.println(s); // 51 }}
/* 关于Java中的关系运算符: > >= < <= == != 注意: 关系运算符运算的结果都是布尔类型:true false 关系运算符,比较原理: int a = 10; int b = 10; a==b 比较的是a和b中保存的10这个值之间的比较 */ public class OperaterTest02{ public static void main(String[] args){ int a = 10; int b = 10; System.out.println(a>b); // false System.out.println(a>=b); // true System.out.println(a
/* 关于Java语言当中的逻辑运算符: & 逻辑与 【两边的算子都为true,结果为true】 | 逻辑或 【两边的算子一边为true,结果为true】 ! 逻辑非 【!false 为 真;!true 为 假;是单目运算符】 ^ 逻辑异或 【两边的算子只要是不一样,结果就为真】 && 短路与 || 短路或 1、逻辑运算符两边的算子都是布尔类型的,最后的结果也是布尔类型的 2、短路与和逻辑与最终的运算结果一样,只不过短路与存在短路现象 3、短路或和逻辑与最终的运算结果一样,只不过短路或存在短路现象 4、什么情况下发生短路现象? 5、什么情况下使用短路与,什么情况下使用短路或运算符?*/public class OperatorTest03{ public static void main(String[] args){ System.out.println(5 > 1 & 5 > 4); // true System.out.println(true | true); // true System.out.println(true | false); // true System.out.println(false | false); // false System.out.println(!false); // true System.out.println(!true); // false System.out.println(true ^ true); // false System.out.println(true ^ false); // true System.out.println(false ^ false); // false // 短路与和逻辑与的区别 /* int x = 10; int y = 5; System.out.println(x < y & ++x < y); // false System.out.println(x); // 11 */ int x = 10; int y = 5; // 短路与 // x < y 为false,整个表达式的结果为false // 短路与不再往下执行了,这种现象称为短路现象 // 短路与才有短路现象,逻辑与没有短路现象 System.out.println(x < y && ++x < y); // false System.out.println(x); // 10 /* 从某个角度而言,短路与更智能,由于后面的表达式可能不执行,执行效率较高, 短路与比逻辑与更长用 但是在某些特殊的业务逻辑当中,要求运算符两边的算子都要执行,这时候只能使用逻辑与 短路与可能导致右边的算子不执行 */ /* 什么情况下发生短路与? 左边算子为false 什么情况下发生短路或? 第一个表达式运算结果为true */ }}
/* 关于Java语言当中的赋值运算符: 基本赋值运算符: = 扩展的赋值运算符: += -= *= /= %= 1、赋值类运算符的优先级:先执行等号右边的,将执行结果赋值给等号左边的变量。 2、注意以下代码: byte i = 10; i += 5; //等同于 (byte)(i + 5); long z = 10L; int y = 5; y += z; // 等同于 (int)(y + z); 3、重要结论:扩展类赋值运算符不改变运算结果的类型,假如变量最初是byte类型 最终该变量也是 byte类型。在底层运算的时候添加了强制类型转换,只不过我们看不见。 */public class OperatorTest04{ public static void main(String[] args){ /* byte b = 10; b += 5; System.out.println(b); // 15 */ byte b = 10; // b = 10 + 5; // 可以 // 编译报错 // 编译阶段只检查语法,不运行程序,b是byte类型,b + 5是int类型, // 大容量向小容量转换,强制类型转换 // b = b + 5; // 纠正 b = (byte)(b + 5); System.out.println(b); byte x = 10; x += 5; // x += 5其实不等同于 x = x + 5;等同于x = (byte)(x + 5); System.out.println(x); // 15 // 【由以上例子可以说明】以下程序编译正确 byte z = 0; z += 128; // 等同于:z = (byte)(z + 128);虽然超出byte类型的取值范围但是其等同前面 System.out.println(z); // -128 损失精度 }}
/* 关于Java语言当中的“+”运算符: 1、“+”运算符有两个作用: * 加法运算,求和 * 字符串连接运算 2、当“+”运算符两边都是数字,执行加法运算; 3、只要一边是字符串则执行字符串连接运算;并且连接运算之后的结果也是字符串å 数字 + 数字 ――――――》数字【加法运算】 字符串 + ?? ――――――》 字符串【字符串连接运算】 4、一个表达式中可以添加多个“+”,在没有添加小括号的前提下,遵循从左至右依次执行*/public class OperatorTest05{ public static void main(String[] args){ System.out.println(10 + 20 + "30"); // "3030" 第一个加号是求和,第二个加号是字符串连接 System.out.println(10 + ( 20 + "30")); // "102030" // 要求在控制台输出"10 + 20 = 30" int a = 10; int b = 20; System.out.println("10 + 20 =" + a + b); // "10 + 20 =1020" 字符串连接,从左至右 // 注意:动态输出 System.out.println("10 + 20 =" + (a + b)); // "10 + 20 =30" System.out.println(a + "+" + b + "=" + (a + b)); // 动态拼接 "10 + 20 =30" // String不是基本数据类型,是引用数据类型 String s = "abc"; // 编译错误:类型不兼容 // String ss = 10; String username = "zhangsan"; System.out.println("欢迎"+username+"回来!"); }}
/*
关于Java语言当中的三目运算符/三元运算符:
1、语法规则:
布尔表达式 ? 表达式1 : 表达式2
2、三元运算符的执行原理:
* 布尔表达式为true,选择表达式1为整个表达式的执行结果
* 布尔表达式为false,选择表达式2为整个表达式的执行结果
*/
public class OperatorTest06
{
public static void main(String[] args){
// 编译错误,不是一个完整的Java语句
// 10;
// 编译错误,不是一个完整的Java语句
// '男';
// 布尔类型变量
boolean sex = false;
//分析以下程序是否编译通过
// 编译报错:不是一个完整的Java语句
// sex ? '男' : '女';
char c = sex ? '男' : '女';
System.out.println(c); //女
sex = true;
c = sex ? '男':'女';
System.out.println(c); //男
// 编译报错
// 语法错误:运行结果可能是String,也可能是char类型,不能用char来接收结果
/*
sex = false;
char c1 = sex ? "男":'女';
*/
System.out.println(sex ? "男":'女'); // 男 可以
String s = sex ? "男的":"女的"; // 可以
System.out.println(s); // 男的
}
}
5、数据类型
* 基本数据类型
byte
short
int
long
double
float
char
boolean
* 引用数据类型
System.class SUN公司提供的
String.class SUN公司提供的
Student.class 程序员自定义的
Customer.class 程序员自定义的
…
总结:
1、jvm【Java虚拟机】包括三块主要的内存空间:方法区内存、堆内存、栈内存;
2、方法区内存、堆内存各有一个,栈内存是一个线程一个栈内存
3、方法调用的时候,该方法所需要的内存空间,在栈中分配,称为压栈;方法执
行结束,该方法所属的内存空间释放,称为弹栈
4、栈中主要存储的是方法体中的局部变量
5、方法的代码片段已经整个类的代码片段都存放在方法区内存中,在类加载的时候这些代码载入
6、在程序执行过程中new出的对象,存放在堆内存中,对象内部有实例对象,因此实例对象存储在
堆内存中;
7、变量分类
关于Java的集成开发环境【集成开发环境:IDE】
1、* 没有IDE
- 需要安装jdk,需要配置环境变量,需要手动将Java源文件编译为.class字节码文件,
编写Java源文件没有错误提示
* 现在比较厉害的IDE
- eclipse
- intelij IDEA
- myeclipse
- NetBeans
- JBuilder
2、eclipse使用
* workspace:工作区
* 每个eclipse可以开启多个会话,每个会话对应不同的工作区
* .metadata文件夹:存储着当前eclipse的工作状态【比如自己设置的布局,存储】
* .metadata文件夹删除之后,再次进入是一个新的工作状态,但是会发现eclipse上的项目丢失了,
这里只是丢失的eclipse上的项目,硬盘上的项目没有丢失
* 窗口不小心关闭
window ---》showview ---> Other ---> 输入自己需要找的窗口名称
* eclipse为Java程序员准备了对应不同开发的布局方式
- 企业级开发:Java EE开发的专用布局 ---》java Enterprise
- 普通Java开发:JavaSE 开发的专用布局 ---》Java
* 重点窗口介绍
- Package Explore:可以看到Java源文件【Project Explore/Navigator】
* 工作区workspace中最基本的单元是:Project[工程/项目]
* Java运行环境jre的配置,可以使用eclipse自带的,也可以使用程序员自己安装的jre
*Project layout:工程目录布局
- 多数情况下使用两个独立的文件夹存储源码(src)和字节码文件(bin)
* 在src下新建软件包:package机制
- 在src目录上右键new -- package
- 给package起名
* 在package下创建一个Java类
- 在包上右键class
* 显示行号
Java源程序左侧栏右键,选择Show Line Numbers
Ctrl + Alt + down
注意:eclipse中的Java源文件有时候不保存是不会编译的,时刻记住:Ctrl + S保存
包package 是Java语法中的一部分