传智播客 刘意_2015年Java基础视频-深入浅出精华版 笔记(day01~day10)(2015年11月17日20:51:59)
2015-08-30 13:09
597 查看
本笔记是个人笔记+摘录笔记相结合,非完全原创
day01
win 7系统打开DOS有趣方法:按住shift+右键,单击“在此处打开命令窗口”(注意:在此处可以是任何的文件夹,不一定是桌面)
用DOS删除的文件不可以在回收站恢复?!!
常用DOS命令
d: 回车 盘符切换
dir(directory):列出当前目录下的文件以及文件夹
md (make directory) : 创建目录(创建文件夹)
rd (remove directory): 删除目录(删除文件夹,注意:前提是文件夹必须是空的!!)
如果想删除不是空的文件夹(比如删除aaaaa文件夹),可以用命令 rd /s aaaaa(会有删除提示)或者rd /s /q aaaaa(静默删除)
cd (change directory)改变指定目录(进入指定目录)
cd.. : 退回到上一级目录
cd\: 退回到根目录
del (delete): 删除文件,删除一堆后缀名一样的文件*.txt
exit : 退出dos命令行
cls : (clear screen)清屏
第一个程序:HelloWorld案例(掌握)
class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
(1)程序解释:
A:Java程序的最基本单位是类,所以我们要定义一个类。
格式:class 类名
举例:class HelloWorld
B:在类中写内容的时候,用大括号括起来。
C:Java程序要想执行,必须有main方法。
格式:public static void main(String[] args)
D:要指向那些东西呢,也用大括号括起来。
E:你要做什么呢?今天我们仅仅做了一个简单的输出
格式:System.out.println("HelloWorld");
注意:""里面的内容是可以改动的。
(2)Java程序的开发执行流程:
A:编写java源程序(.java)
B:通过javac命令编译生成.class文件
C:通过java命令运行.class文件
常见的问题(掌握)
(1)扩展名被隐藏
如何找到:工具--文件夹选项--查看--去除隐藏扩展名的那个勾勾
(2)要求文件名称和类名一致。
实际上不这样做也是可以的。
但是,注意:
javac后面跟的是文件名+扩展名
java后面跟的类名不带扩展名
(3)Java语言严格区分大小写,请注意。
还有就是单词不要写错了。
(4)见到非法字符: \65307肯定是中文问题。
写程序要求标点符号必须全部是英文状态。
(5)括号的配对问题。
一般来说,括号都是成对出现的。
(6)遇到
在类 HelloWorld 中找不到主方法, 请将主方法定义为
肯定是主方法的格式问题。
path环境变量
path环境变量的作用
保证javac命令可以在任意目录下运行。
同理可以配置qq等
day2
1.java关键字--组成关键字的字母全部小写
注意:goto和const作为保留字存在,目前并不使用(在JDK的新版本中可能提升为关键字)
2.demo:案例,演示
3.Java标识符
可以是
英文大小写字母
数字字符
$和_
注意:
A.不能以数字开头
B.不能是Java中的关键字
C.Java语言严格区分大小写
4.常见的命名规则(重点):见名知意
举例:我要定义一个学生类
class Student {}
class S{}
包:其实就是文件夹,用于把相同的类名进行区分
全部小写
单级:liuyi
多级:cn.itcast(解析:cn是一个文件夹,itcast也是一个文件夹,cn文件夹里包含有itcast文件夹)
cn
itcast
类或者接口:
一个单词:单词的首字母必须大写
举例:Student,Dog
多个单词:每个单词的首字母必须大写
举例:HelloWorld,StudentName
方法或者变量:
一个单词:单词的首字母小写
举例:main,age
多个单词:从第二个单词开始,每个单词的首字母大写
举例:studentAge,showAllNames()
常量:
一个单词:全部大写
举例:PI
多个单词:每个字母都大写,用_隔开
举例:STUDENT_MAX_AGE
5.Java中注释的分类及格式
单行注释://
多行注释:/星 星/
注意:多行不可以嵌套使用,而单行是可以的
文档注释:被javadoc工具解析生成一个说明书
用注释写的一个Java案例
===========================华丽的分割线=========================================
/*
需求:我准备写一个java程序,把“HelloWorld”这句话输出在控制台
分析:A:要写一个java程序,必须定义类
B:把数据能够输出,说明我们的程序是可以独立运行的,而程序要独立运行,必须定义main方法
C:把数据输出在控制台,必须使用输出语句
实现:
A:java语言提供了一个关键字:class用来定义类,后面跟的是类名
B:main方法的格式是固定的:
public static void main(String[] args) {
}
C:输出语句的格式是固定的:
System.out.println("HelloWorld");
"HelloWorld"这个内容是可以改变的
*/
//这是我的HelloWorld案例
class HelloWorld {
/*
为了程序能够独立运行,定义main方法
main方法是程序的入口
被jvm自动调用
*/
public static void main(String[] args) {
//为了把数据显示在控制台,我们就使用了输出语句
System.out.println("HelloWorld");
}
}
===========================华丽的分割线=============================================
6.常量:
在程序执行过程中,其值不发生改变的量。
分类:
A:字面值常量
B:自定义常量(后面讲)
字面值常量
A:字符串常量 用双引号括起来的内容。
B:整数常量 所有的整数
举例:100, 200
C:小数常量 所有的小数
举例:10.23,110.11
D:字符常量 用单引号括起来的内容
举例:‘a’,‘A’,‘0’
错误的:‘ab’
E:布尔常量 比较特殊
举例:true,false
F:空常量 后面讲
举例:null
7.Java进制
Java针对整数常量提供了4种表现形式
二进制(jdk7以后有)
八进制
十进制
十六进制
8.快速的进制转换法
8421码,是bcd码一种。
它表达的意思是每一个二进制位上的数据对应一个固定的值,
只需要把对应的1位置的数据值给相加,即可得到该二进制对应的十进制的值
二进制 1 1 1 1 1 1 1 1
十进制 128 64 32 16 8 4 2 1
例
二进制到十进制的转换
1010100 = 64 + 16 + 4 = 84;
十进制到二进制的转换
100 = 0b1100100(对照着看,首先100<128,所以第八位为0;然后100>64,第七位为1;接着,100-64=36,36>32,所以第六位为1;然后,36-32=4,4<16,所以第五位为0;然后,4<8,第四位为0;然后,4=4,所以第三位为1;
然后,0<2,第二位为0;然后0<1,第一位为0,总的来说是01100100,去掉首位的0就是1100100,再规范化表示为0b1100100)
第一个程序:HelloWorld案例(掌握)
class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
(1)程序解释:
A:Java程序的最基本单位是类,所以我们要定义一个类。
格式:class 类名
举例:class HelloWorld
B:在类中写内容的时候,用大括号括起来。
C:Java程序要想执行,必须有main方法。
格式:public static void main(String[] args)
D:要指向那些东西呢,也用大括号括起来。
E:你要做什么呢?今天我们仅仅做了一个简单的输出
格式:System.out.println("HelloWorld");
注意:""里面的内容是可以改动的。
(2)Java程序的开发执行流程:
A:编写java源程序(.java)
B:通过javac命令编译生成.class文件
C:通过java命令运行.class文件
常见的问题(掌握)
(1)扩展名被隐藏
如何找到:工具--文件夹选项--查看--去除隐藏扩展名的那个勾勾
(2)要求文件名称和类名一致。
实际上不这样做也是可以的。
但是,注意:
javac后面跟的是文件名+扩展名
java后面跟的类名不带扩展名
(3)Java语言严格区分大小写,请注意。
还有就是单词不要写错了。
(4)见到非法字符: \65307肯定是中文问题。
写程序要求标点符号必须全部是英文状态。
(5)括号的配对问题。
一般来说,括号都是成对出现的。
(6)遇到
在类 HelloWorld 中找不到主方法, 请将主方法定义为
肯定是主方法的格式问题。
path环境变量
path环境变量的作用
保证javac命令可以在任意目录下运行。
同理可以配置qq等
day2
1.java关键字--组成关键字的字母全部小写
注意:goto和const作为保留字存在,目前并不使用(在JDK的新版本中可能提升为关键字)
2.demo:案例,演示
3.Java标识符
可以是
英文大小写字母
数字字符
$和_
注意:
A.不能以数字开头
B.不能是Java中的关键字
C.Java语言严格区分大小写
4.常见的命名规则(重点):见名知意
举例:我要定义一个学生类
class Student {}
class S{}
包:其实就是文件夹,用于把相同的类名进行区分
全部小写
单级:liuyi
多级:cn.itcast(解析:cn是一个文件夹,itcast也是一个文件夹,cn文件夹里包含有itcast文件夹)
cn
itcast
类或者接口:
一个单词:单词的首字母必须大写
举例:Student,Dog
多个单词:每个单词的首字母必须大写
举例:HelloWorld,StudentName
方法或者变量:
一个单词:单词的首字母小写
举例:main,age
多个单词:从第二个单词开始,每个单词的首字母大写
举例:studentAge,showAllNames()
常量:
一个单词:全部大写
举例:PI
多个单词:每个字母都大写,用_隔开
举例:STUDENT_MAX_AGE
5.Java中注释的分类及格式
单行注释://
多行注释:/星 星/
注意:多行不可以嵌套使用,而单行是可以的
文档注释:被javadoc工具解析生成一个说明书
用注释写的一个Java案例
===========================华丽的分割线=========================================
/*
需求:我准备写一个java程序,把“HelloWorld”这句话输出在控制台
分析:A:要写一个java程序,必须定义类
B:把数据能够输出,说明我们的程序是可以独立运行的,而程序要独立运行,必须定义main方法
C:把数据输出在控制台,必须使用输出语句
实现:
A:java语言提供了一个关键字:class用来定义类,后面跟的是类名
B:main方法的格式是固定的:
public static void main(String[] args) {
}
C:输出语句的格式是固定的:
System.out.println("HelloWorld");
"HelloWorld"这个内容是可以改变的
*/
//这是我的HelloWorld案例
class HelloWorld {
/*
为了程序能够独立运行,定义main方法
main方法是程序的入口
被jvm自动调用
*/
public static void main(String[] args) {
//为了把数据显示在控制台,我们就使用了输出语句
System.out.println("HelloWorld");
}
}
===========================华丽的分割线=============================================
6.常量:
在程序执行过程中,其值不发生改变的量。
分类:
A:字面值常量
B:自定义常量(后面讲)
字面值常量
A:字符串常量 用双引号括起来的内容。
B:整数常量 所有的整数
举例:100, 200
C:小数常量 所有的小数
举例:10.23,110.11
D:字符常量 用单引号括起来的内容
举例:‘a’,‘A’,‘0’
错误的:‘ab’
E:布尔常量 比较特殊
举例:true,false
F:空常量 后面讲
举例:null
7.Java进制
Java针对整数常量提供了4种表现形式
二进制(jdk7以后有)
八进制
十进制
十六进制
8.快速的进制转换法
8421码,是bcd码一种。
它表达的意思是每一个二进制位上的数据对应一个固定的值,
只需要把对应的1位置的数据值给相加,即可得到该二进制对应的十进制的值
二进制 1 1 1 1 1 1 1 1
十进制 128 64 32 16 8 4 2 1
例
二进制到十进制的转换
1010100 = 64 + 16 + 4 = 84;
十进制到二进制的转换
100 = 0b1100100(对照着看,首先100<128,所以第八位为0;然后100>64,第七位为1;接着,100-64=36,36>32,所以第六位为1;然后,36-32=4,4<16,所以第五位为0;然后,4<8,第四位为0;然后,4=4,所以第三位为1;
然后,0<2,第二位为0;然后0<1,第一位为0,总的来说是01100100,去掉首位的0就是1100100,再规范化表示为0b1100100)
9.原码反码补码
原码:
正数的原码最高位是0;
负数的原码最高位是1;
其他的是数值位。
符号位 数值位
+7 0 0000111
-7 1 0000111
反码:
正数的反码与原码相同。
负数的反码与原码是符号不变,数值位取反(0变1,1变0)
+7 0 0000111
-7 1 1111000
补码:
正数的补码与原码相同
负数的补码是在反码的基础上加1.
+7 0 0000111
-7 1 1111001
有符号数据表示法的练习
A:已知某数X的原码为10110100B,试求X的补码和反码。
符号位 数值位
原码: 10110100
反码: 11001011
补码: 11001100
B:已知某数X的补码11101110B,试求其原码。
符号位 数值位
补码: 11101110
反码: 11101101
原码: 10010010
10.数据类型:Java是一种强类型的语言,针对每一种数据都定义了明确的数据类型。
数据类型分类:
A:基本数据类型
B:引用数据类型(类,接口,数值)
基本数据类型:4类8种
A:整数 占用字节数
byte 1
short 2
int 4
long 8
B:浮点数
float 4
double 8
C:字符
char 2
D:布尔
boolean
1
注意:
整数默认是int类型
浮点数默认是double类型。
长整型后缀用L或者l标记。建议使用L。
例如
在Java中,
long j = 10000000000;
System.out.println(j);
编译时会报错 错误: 过大的整数: 10000000000,因为整数(这里是10000000000)默认是int类型
解决办法 long j = 10000000000L;
单精度浮点数用F或者f标记。建议使用F。
例如
在Java中,
float f = 12.345;
System.out.println(f);
编译时会报错 错误: 不兼容的类型: 从double转换到float可能会有损失
解决办法 float f = 12.345F;
11.数据类型转换
默认转换(从小到大的转换)
A:byte,short,char—int—long—float—double
B:byte,short,char相互之间不转换,他们参与运算首先转换为int类型
举例
=================================================================
byte a = 3;
int b = 4;
byte c = a + b;//有问题
int d = a + b;//没有问题
=================================================================
上述 byte c = a + b;//有问题
如何解决?用强制类型转换
12.强制转换:
从大的数据类型到小的数据类型。
格式:
目标数据类型 变量 = (目标数据类型) (被转换的数据);
注意:
不要随意的去使用强制转换,因为它隐含了精度损失问题。
那么,
//用强制类型转换改进
byte c = (byte) (a + b);
System.out.println(c);
13.思考题:看看下面两个定义有没有区别呢?
float f1 = (float)12.345;
float f2 = 12.345f;
f1其实是通过一个double类型转换过来的。
而f2本身就是一个float类型。(建议用f2的写法)
14.面试题
A面试题:
byte b1=3,b2=4,b;
b=b1+b2;
b=3+4;
哪句是编译失败的呢?为什么呢?
答:b = b1 + b2;是有问题的。
因为变量相加,会首先看类型问题,最终把结果赋值的也会考虑类型问题。
常量相加,首先做加法,然后看结果是否在赋值的数据类型范围内,如果不是,才报错。
也就是说。b = b1 + b2; -----这个是类型提升,所有有问题。b1 + b2首先整体提升为int类型(byte,short,char相互之间不转换,他们参与运算首先转换为int类型),int类型的(b1+b2)赋值给byte类型的b,所以有损失精度的错误。
b = 3 + 4; //常量,先把结果计算出来,然后看是否在byte的范围内,如果在就不报错。也就是说,编译器把3+4看做一个常量而不是变量的加法运算。所以不报错
15.强制转换数据溢出后的结果怎么算(一个实例)
byte b = 130;有没有问题?如果我想让赋值正确,可以怎么做?结果是多少呢?
//我们可以使用强制类型转换
byte b = (byte) 130;
//结果是多少呢?
System.out.println(b);
分析过程:
我们要想知道结果是什么,就应该知道是如何进行计算的。
而我们又知道计算机中数据的运算都是补码进行的。
而要得到补码,首先要计算出数据的二进制。
A:获取130这个数据的二进制。
00000000 00000000 00000000 10000010
这是130的原码,也是反码,还是补码。
B:做截取操作,截成byte类型的了。
10000010
这个结果是补码。
C:已知补码求原码。(注意不要漏掉这一步,因为内存中操作的是补码,而我们看到的是补码,所以还要转换成原码)
符号位 数值位
补码: 10000010
反码: 10000001
原码: 11111110
16.
//直接输出一个字符
System.out.println('a'); //输出a
//输出一个字符和一个整数做加法
System.out.println('a'+1); //输出98
ASCII码表。
记住三个值:
'a' 97
'A' 65
'0' 48注意
17.字符串参与运算
System.out.println("hello"+'a'+1); //输出helloa1,hello优先与‘a’结合
System.out.println('a'+1+"hello"); //输出98hello,‘a’优先与1结合,形成98再与hello结合
System.out.println("5+5="+5+5); //输出5+5=55,字符串与数字5先结合
System.out.println(5+5+"=5+5"); //输出10=5+5,5+5优先形成10,再与字符串结合
补:‘a’+1有类型提升???!
day3
1.在定义Long或者Float类型变量的时候,要加L或者f。
整数默认是int类型,浮点数默认是double。
byte,short在定义的时候,他们接收的其实是一个int类型的值。
这个是自己做了一个数据检测的,如果不再它们的范围内,就报错。
float表示的数据范围比long的范围要大
long:2^63-1
float:3.4*10^38 > 2*10^38 > 2*8^38 = 2*2^3^38 = 2*2^114 > 2^63-1
2.面试题:Java语言中的字符char可以存储一个中文汉字吗?为什么呢?
可以。因为java语言中的字符占用两个字节。(Java中char占两个字节,C语言中char占一个字节)
Java语言采用的是Unicode编码。
3.
A:整数相除只能得到整数。如果想得到小数,必须把数据变化为浮点数类型
B:/获取的是除法操作的商,%获取的是除法操作的余数
=========================================================================
System.out.println(x/y); //整数相除只能得到整数
//我就想得到小数,该肿么办呢?
//只需要把操作的数据中任意的一个数据变为浮点数
System.out.println(x*1.0/y);
//%的应用
System.out.println(x%y); //得到的是余数
==========================================================================
4.++,--运算符的使用
//参与运算使用
int a = 3;
int b = 4;
int c = a++;
int d = b--;
System.out.println("a:"+a); //输出为4
System.out.println("b:"+b); //输出为3
System.out.println("c:"+c); //输出为3
System.out.println("d:"+d); //输出为4
5.一个面试题
面试题:
short s=1;s = s+1;
short s=1;s+=1;
上面两个代码有没有问题,如果有,那里有问题。
class OperatorTest {
public static void main(String[] args) {
//short s = 1;
//s = s + 1;
//System.out.println(s);
short s = 1;
s += 1; //好像是 s = s + 1;
System.out.println(s);
}
}
为什么第二个木有问题呢?
扩展的赋值运算符其实隐含了一个强制类型转换。
s += 1;
不是等价于 s = s + 1;
而是等价于 s = (s的数据类型)(s + 1);
(个人理解)也就是说,s = s + 1中的s + 1包含了加法运算,short类型出现了提升(提升为int类型)
而s+=1本身隐含了强制的类型转换
6.逻辑运算符:
&,|,^,!
&&,||
特点:
逻辑运算符一般用于连接boolean类型的表达式或者值。
表达式:就是用运算符把常量或者变量连接起来的符合java语法的式子。
算术表达式:a + b
比较表达式:a == b
结论:
&逻辑与:有false则false。
|逻辑或:有true则true。
^逻辑异或:相同为false,不同为true。
举例:情侣关系。男男,男女,女男,女女
!逻辑非:非false则true,非true则false。
特点:偶数个不改变本身。
例如
int a = 3;
int b = 4;
int c = 5;
//&逻辑与
System.out.println((a > b) & (a > c)); //false & false = false
System.out.println((a > b) & (a < c)); //false & true = false
System.out.println((a < b) & (a > c)); //true & false = false
System.out.println((a < b) & (a < c)); //true & true = true
7.Java中&&与&
&&和&的区别? 同理||和|的区别?
A:最终结果一样。
B:&&具有短路效果。左边是false,右边不执行。
开发中常用的逻辑运算符:
&&,||,!
示例
//boolean b1 = ((x++ == 3) & (y++ == 4));
//boolean b1 = ((x++ == 3) && (y++ == 4));
//boolean b1 = ((++x == 3) & (y++ == 4));
boolean b1 = ((++x == 3) && (y++ == 4));
System.out.println("x:"+x);
System.out.println("y:"+y);
System.out.println(b1);
8.位运算符:
&,|,^,~
<<,>>,>>>
注意:
要做位运算,首先要把数据转换为二进制。
例子
int a = 3;
int b = 4;
System.out.println(3 & 4);
System.out.println(3 | 4);
System.out.println(3 ^ 4);
System.out.println(~3);
分析:因为是位运算,所以我们必须先把数据换算成二进制。
3的二进制:11
00000000 00000000 00000000 00000011
4的二进制:100
00000000 00000000 00000000 00000100
&位与运算:有0则0。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000000
结果是:0
|位或运算:有1则1。
00000000 00000000 00000000 00000011
|00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
^位异或运算:相同则0,不同则1。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
~按位取反运算符:0变1,1变0
00000000 00000000 00000000 00000011
~11111111 11111111 11111111 11111100 (补码)
补码:11111111 11111111 11111111 11111100
反码:11111111 11111111 11111111 11111011
原码:10000000 00000000 00000000 00000100
结果是:-4
9.^的特点:一个数据位异或两次,该数本身不变。(^指的是异或运算符)
例如
int a = 10;
int b = 20;
System.out.println(a ^ b ^ b);//10
System.out.println(a ^ b ^ a);//20
10.一道面试题:
请自己实现两个整数变量的交换(默认int类型.)
例如
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b);
方式1:使用第三方变量(开发中用的)
int c = a;
a = b;
b = c;
System.out.println("a:"+a+",b:"+b);
System.out.println("------------");
方式2:用位异或实现(面试用)
左边:a,b,a
右边:a ^ b
a = a ^ b;
b = a ^ b; //a ^ b ^ b = a
a = a ^ b; //a ^ b ^ a = b
System.out.println("a:"+a+",b:"+b);
方式3:用变量相加的做法
a = a + b; //a=30
b = a - b; //b=10
a = a - b; //a=20
System.out.println("a:"+a+",b:"+b);
方式4:一句话搞定
b = (a+b) - (a=b); //b=30-20=10,a=20
System.out.println("a:"+a+",b:"+b);
11.<<:左移 左边最高位丢弃,右边补齐0
>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1
>>>:无符号右移 无论最高位是0还是1,左边补齐0
//<< 把<<左边的数据乘以2的移动次幂
System.out.println(3 << 2); //3*2^2 = 3*4 = 12;
//>> 把>>左边的数据除以2的移动次幂
System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6
System.out.println(24 >>> 2);
System.out.println(-24 >> 2);
System.out.println(-24 >>> 2);
分析
计算出3的二进制:11
00000000 00000000 00000000 00000011
(00)000000 00000000 00000000 0000001100
>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
1111111111 11111111 11111111 111010(00) 补码
补码:1111111111 11111111 11111111 111010
反码:1111111111 11111111 11111111 111001
原码:1000000000 00000000 00000000 000110
结果:-6
>>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
0011111111 11111111 11111111 111010(00)
结果:
update 2015年9月9日00:27:03
12.&&:结果和&是一样的,只不过有短路效果。左边是false,右边不执行。
||:结果和|是一样的,只不过有短路效果。左边是true,右边不执行。
update 2015年9月14日23:13:32
Day 4
1.switch:表示这是switch选择结构
表达式:这个地方的取值是有限定的
byte,short,int,char
JDK5以后可以是枚举
JDK7以后可以是字符串
面试题
byte可以作为switch的表达式吗?
long可以作为switch的表达式吗?
String可以作为switch的表达式吗?
答:byte可以,long不可以,String在jdk7后可以
2.switch要注意break问题
例如
int a = 2;
int b = 3;
switch(a)
{
default:
b++;
case 3:
b++;
case 4:
b++;
}
switch语句只在遇到break才能停止,否则会一直执行下去
3.if语句和switch语句的区别?
if语句:
A:针对结果是boolean类型的判断
B:针对一个范围的判断
C:针对几个常量值的判断
switch语句:
针对几个常量值的判断
4.break
break:中断的意思
使用场景:
A:switch语句中
B:循环语句中。
(循环语句中加入了if判断的情况)
注意:离开上面的两个场景,无意义。
如何使用呢?
A:跳出单层循环
B:跳出多层循环
要想实现这个效果,就必须知道一个东西。带标签的语句。
格式:
标签名: 语句
带标签的break语句相当于goto语句
例子:
//跳出单层循环
for(int x=0; x<10; x++) {
if(x == 3) {
break;
}
System.out.println("HelloWorld");
}
//跳出多层循环
wc:for(int x=0; x<3; x++) {
nc:for(int y=0; y<4; y++) {
if(y == 2) {
//break nc;
break wc;
}
System.out.print("*");
}
System.out.println();
}
break wc;语句跳出两个for循环,而普通的break语句只能跳出内层单循环。
5.return:返回
A:用于结束方法的;
B:一旦遇到return,程序就不会在继续往后执行。
day5
1.方法
方法就是完成特定功能的代码块
在很多语言里面都有函数的定义
函数在Java中被称为方法
参数:
实际参数:就是实际参与运算的。
形式参数;就是方法定义上的,用于接收实际参数的。
2.方法调用
例子
public static void main(String[] args) {
int x = 10;
int y = 20;
//方式1:单独调用
//sum(x,y);
//方式2:输出调用
//System.out.println(sum(x,y));
//System.out.println(30);
//方式3:赋值调用
int result = sum(x,y);
//result在这里可以进行操作
System.out.println(result);
}
public static int sum(int a,int b) {
return a + b;
}
3.方法重载
实例
方法重载:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载特点:
与返回值类型无关,只看方法名和参数列表
在调用时,虚拟机通过参数列表的不同来区分同名方法
简言之:在同一个类中,方法名相同,参数列表不同,与返回值类型无关。
参数列表不同:
A:参数个数不同
B:参数类型不同
4.数组
数组:存储同一种数据类型的多个元素的容器。
定义格式:
A:数据类型[] 数组名;
B:数据类型 数组名[];
举例:
A:int[] a; 定义一个int类型的数组a变量
B:int a[]; 定义一个int类型的a数组变量
推荐使用第一种格式
对数组进行初始化
a:动态初始化 只指定长度,由系统给出初始化值
b:静态初始化 给出初始化值,由系统决定长度
动态初始化的格式:
数据类型[] 数组名 = new 数据类型[数组长度];
举例:
int[] arr = new int[3];
如何获取数组中的元素呢?
通过:
数组名[索引]
索引其实就是每个元素的编号,从0开始,最大索引是数组的长度-1。
例子
int[] arr = new int[3];
//用数组名和编号的配合就可以获取数组中的指定编号的元素。这个编号的专业叫法:索引
//通过数组名访问数据的格式是:数组名[索引];
System.out.println(arr); //[I@175078b 地址值。
System.out.println(arr[0]);//0
System.out.println(arr[1]);//0
System.out.println(arr[2]);//0
数组的静态初始化:
格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
简化格式:
数据类型[] 数组名 = {元素1,元素2,…};
举例:
int[] arr = new int[]{1,2,3};
简化后:
int[] arr = {1,2,3};
注意事项:
不要同时动态和静态进行。
如下格式:
int[] arr = new int[3]{1,2,3}; //错误
5.数组操作的两个常见小问题:
ArrayIndexOutOfBoundsException:数组索引越界异常
原因:你访问了不存在的索引。
例如
int[] arr = {1,2,3};
System.out.println(arr[3]);
NullPointerException:空指针异常
原因:数组已经不在指向堆内存了。而你还用数组名去访问元素。
例如
//引用类型的常量:空常量 null
arr = null;
System.out.println(arr[0]);
6.数组逆序
例子
逆序
方式1:
方式2:
7.查找元素对应的索引值
基本查找
方式1:
方式2(特别注意!):
day06
1.二维数组
就是元素为一维数组的一个数组。
格式1
数据类型[][] 变量名 = new 数据类型[m]
;
m表示这个二维数组有多少个一维数组
n表示每一个一维数组的元素个数
举例:
int[][] arr = new int[3][2];
定义了一个二维数组arr
这个二维数组有3个一维数组,名称是arr[0],arr[1],arr[2]
每个一维数组有2个元素,可以通过arr[m]
来获取
表示获取第m+1个一维数组的第n+1个元素
注意:
A:以下格式也可以表示二维数组
a:数据类型 数组名[][] = new 数据类型[m]
;
b:数据类型[] 数组名[] = new 数据类型[m]
;
一个实例
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = new int[3][2];
//定义了一个二维数组arr
//这个二维数组有3个一维数组的元素
//每一个一维数组有2个元素
//输出二维数组名称
System.out.println(arr); //地址值 [[I@175078b
//输出二维数组的第一个元素一维数组的名称
System.out.println(arr[0]); //地址值 [I@42552c
System.out.println(arr[1]); //地址值 [I@e5bbd6
System.out.println(arr[2]); //地址值 [I@8ee016
//输出二维数组的元素
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
}
二维数组格式1的内存图解
格式2
数据类型[][] 数组名 = new 数据类型[m][];
m:表示这个二维数组有多少个一维数组。
列数没有给出,可以动态的给。这一次是一个变化的列数。
举例
public static void main(String[] args) {
//定义数组
int[][] arr = new int[3][];
System.out.println(arr); //[[I@175078b
System.out.println(arr[0]); //null
System.out.println(arr[1]); //null
System.out.println(arr[2]); //null
//动态的为每一个一维数组分配空间
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[1];
System.out.println(arr[0]); //[I@42552c
System.out.println(arr[1]); //[I@e5bbd6
System.out.println(arr[2]); //[I@8ee016
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
//ArrayIndexOutOfBoundsException
//System.out.println(arr[0][2]); //错误
arr[1][0] = 100;
arr[1][2] = 200;
}
格式1,格式2属于动态初始化
格式3
基本格式:
数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
简化版格式:
数据类型[][] 数组名 = {{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
举例:
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
int[][] arr = {{1,2,3},{4,5},{6}};
举例
public static void main(String[] args) {
//定义数组
int[][] arr = {{1,2,3},{4,5},{6}};
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[0][0]); //1
System.out.println(arr[1][0]); //4
System.out.println(arr[2][0]); //6
System.out.println(arr[0][1]); //2
System.out.println(arr[1][1]); //5
//越界
System.out.println(arr[2][1]); //错误
}
2.二维数组的遍历
外循环控制的是二维数组的长度,其实就是一维数组的个数。
内循环控制的是一维数组的长度。
代码如下
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
//arr[0]就是第一个数组
//arr[0] = {1,2,3};
for(int x=0; x<arr[0].length; x++) {
System.out.println(arr[0][x]);
}
System.out.println("--------------");
for(int x=0; x<arr[1].length; x++) {
System.out.println(arr[1][x]);
}
System.out.println("--------------");
for(int x=0; x<arr[2].length; x++) {
System.out.println(arr[2][x]);
}
System.out.println("--------------");
//用循环改进
for(int x=0; x<3; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
System.out.println("--------------");
//3是我们根据上面的代码得出来的
//但是,它不能针对任何的数组都可以这样
//其实外面的这个循环的长度就是二维数组的长度
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
System.out.println("--------------");
//用方法改进
//调用方法
printArray2(arr);
System.out.println("--------------");
//我们再来一个列数是变化的
int[][] arr2 = {{1,2,3},{4,5},{6}};
printArray2(arr2);
}
/*
需求:遍历二维数组
两个明确:
返回值类型:void
参数列表:int[][] arr
*/
public static void printArray2(int[][] arr) {
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
}
3.二维数组累加求和
核心代码
//通过遍历就可以得到每一个二维数组的元素。
for(int x=0; x<arr.length; x++)
{
for(int y=0; y<arr[x].length; y++)
{
//把元素累加即可。
sum += arr[x][y];
}
}
4.Java参数传递问题
Java中的参数传递问题:
基本类型:形式参数的改变对实际参数没有影响。
引用类型:形式参数的改变直接影响实际参数。
例子
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b); //a:10,b:20
change(a,b);
System.out.println("a:"+a+",b:"+b); //??? a:10,b:20
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println(arr[1]); //??? 4
}
public static void change(int a,int b) { //a=10,b=20
System.out.println("a:"+a+",b:"+b); //a:10,b:20
a = b; //a=20
b = a + b; //b=40
System.out.println("a:"+a+",b:"+b); //a:20,b:40
}
public static void change(int[] arr) { //arr={1,2,3,4,5};
for(int x=0; x<arr.length; x++) {
if(arr[x]%2==0) {
arr[x]*=2;
}
}
//arr={1,4,3,8,5};
}
一句话:在Java中,只有值传递,只不过基本类型传递的是基本类型的数据值,而引用类型传递的是地址值
6.面向对象思想
面向对象是基于面向过程的编程思想。
面向过程:强调的是每一个功能的步骤
面向对象:强调的是对象,然后由对象去调用功能
2:面向对象的思想特点
A:是一种更符合我们思想习惯的思想
B:可以将复杂的事情简单化
C:将我们从执行者变成了指挥者
举例:
买电脑:
面向过程:我的了解电脑--了解我自己的需求--找对应的参数信息--去中关村买电脑--讨价还价--买回电脑
面向对象:我知道我要买电脑 -- 班长去给我买 -- 班长就买回来了
洗衣服:
面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来
面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来
吃饭:
面向过程:去超市买菜--摘菜--洗菜--切菜--炒菜--盛起来--吃
面向对象:上饭店吃饭,你--服务员(点菜)--厨师(做菜)--服务员(端菜)--吃
3.开发,设计,特征
面向对象开发
就是不断的创建对象,使用对象,指挥对象做事情。
面向对象设计
其实就是在管理和维护对象之间的关系。
面向对象特征
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
4.面向过程与面向对象
举例:把大象装进冰箱
面向过程:
动作有哪些呢?
A:打开冰箱门
B:装进大象
C:关闭冰箱门
面向对象:
我们怎么才能更符合面向对象思想呢?
A:有哪些类呢?
B:每个类有哪些东西呢?
C:类与类直接的关系是什么呢?
把大象装进冰箱的分析? (如何分析有哪些类呢?UML。名词提取法。)
A:有哪些类呢?
大象
冰箱
Demo
B:每个类有哪些东西呢?
大象:
进去
冰箱:
开门
关门
Demo:
main方法
C:类与类直接的关系是什么呢?
Demo中使用大象和冰箱类的功能。
5.现实世界中是如何描述一个事物的呢?
举例:学生
姓名,年龄,性别...
学习,吃饭,睡觉
属性:该事物的描述信息
行为:该事物能够做什么
我们学习编程语言,是为了模拟现实世界的事物的。
而我们学习的编程语言Java中最基本的单位是:类。
所以,我们就应该把事物通过类来体现出来:
由此,我们就得到了现实世界事物和类的对应关系:
事物: 类:
属性 成员变量
行为 成员方法
类:是一组相关的属性和行为的集合。是一个抽象的概念。
对象:是该类事物的具体表现形式。具体存在的个体。
举例:
学生:类
班长:对象
=================================
现实世界的事物
事物:
属性 人的身高,体重等
行为 人可以学习,吃饭等
Java中用class描述事物也是如此
类:
成员变量 就是事物的属性
成员方法 就是事物的行为
定义类其实就是定义类的成员(成员变量和成员方法)
===========================================================
6.
在一个java文件中写两个类:一个基本的类,一个测试类。
注意:文件名称和测试类名称一致。
如何使用呢?
创建对象使用。
如何创建对象呢?
格式:类名 对象名 = new 类名();
如何使用成员变量呢?
对象名.变量名
如何使用成员方法呢?
对象名.方法名(...)
7……
一个对象的内存图
二个对象的内存图
三个对象的内存图
使用类的内容
a:创建对象? 格式
类名 对象名 = new 类名();
b:如何使用成员变量和成员方法呢
对象名.成员变量
对象名.成员方法()
day07
1.成员变量和局部变量
一个实例
class Varialbe {
//成员变量
//int num = 10;
int num; //0
public void show() {
//int num2 = 20; //局部变量
//可能尚未初始化变量num2
//int num2; //没有默认值
int num2 = 20;
System.out.println(num2);
//int num = 100;
System.out.println(num);
}
}
class VariableDemo {
public static void main(String[] args) {
Varialbe v = new Varialbe();
System.out.println(v.num); //访问成员变量
v.show();
}
}
成员变量和局部变量的区别?
A:在类中的位置不同
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
B:在内存中的位置不同
成员变量:在堆内存
局部变量:在栈内存
C:生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同
成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
注意事项:
局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
例如,上面关于num的输出问题
2.
形式参数的问题:
基本类型:形式参数的改变不影响实际参数(值传递)
引用类型:形式参数的改变直接影响实际参数(引用传递)
===============================================================================
//形式参数是引用类型
class Student {
public void show() {
System.out.println("我爱学习");
}
}
class StudentDemo {
//如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
public void method(Student s) {
//调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();
s.show();
}
}
class ArgsTest {
public static void main(String[] args) {
//形式参数是引用类型的调用
//需求:我要调用StudentDemo类中的method()方法
StudentDemo sd = new StudentDemo();
//创建学生对象
Student s = new Student();
sd.method(s); //把s的地址给到了这里
}
}
===============================================================================
3.匿名对象
匿名对象:就是没有名字的对象。
匿名对象的应用场景:
A:调用方法,仅仅只调用一次的时候。
注意:调用多次的时候,不适合。
那么,这种匿名调用有什么好处吗?
有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
B:匿名对象可以作为实际参数传递
class Student {
public void show() {
System.out.println("我爱学习");
}
}
class StudentDemo {
public void method(Student s) {
s.show();
}
}
class NoNameDemo {
public static void main(String[] args) {
//带名字的调用
Student s = new Student();//虽然也在堆内存里,但是有s地址连接着new Student(),new Student()不会这么快消失(只要s还存在)
s.show();
s.show();//同一个对象被调用两次
System.out.println("--------------");
//匿名对象
//new Student();
//匿名对象调用方法
new Student().show();
new Student().show(); //这里其实是重新创建了一个新的对象。因为这是在堆内存的,调用完就消失了
System.out.println("--------------");
匿名对象可以作为实际参数传递
//匿名对象作为实际参数传递
StudentDemo sd = new StudentDemo();
//Student ss = new Student();
//sd.method(ss); //这里的s是一个实际参数
//匿名对象
sd.method(new Student());
//在来一个
new StudentDemo().method(new Student());
4.
private:私有的。可以修饰成员变量和成员方法。
注意:被private修饰的成员只能在本类中访问。
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
例子
class Student {
String name;
private int age;
//写一个方法对数据进行校验
public void setAge(int a) {
if(a < 0 || age > 120) {
System.out.println("你给的年龄有问题");
}else {
age = a;
}
}
//show()方法,显示所有成员变量值
public void show() {
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
}
}
class StudentDemo {
public static void main(String[] args) {
//创建学生对象
Student s = new Student();
s.show();
System.out.println("--------------");
//给成员变量赋值
s.name = "林青霞";
//s.age = 27;
s.setAge(27);
s.show();
System.out.println("--------------");
//给age赋值
//s.age = -27; //这个数据是不合理的,加上private后age只能在Student类中使用而不能在StudentDemo中使用
//通过方法给值
s.setAge(-27);
s.show();
System.out.println("--------------");
}
}
5.封装和private的应用:
A:把成员变量用private修饰
B:提高对应的getXxx()和setXxx()方法
class Student
{
private String name;
private int age;
public String getName()
{
return name;
}
public void setName(String n)
{
name = n;
}
public int getAge()
{
return age;
}
public void setAge(int a)
{
age = a;
}
}
//测试类
class StudentTest {
public static void main(String[] args)
{
//创建学生对象
Student s = new Student();
//使用成员变量
//错误:被私有修饰了,外界不能直接访问了
//System.out.println(s.name+"---"+s.age);
System.out.println(s.getName()+"---"+s.getAge());
//给成员变量赋值
//s.name = "林青霞";
//s.age = 27;
//通过方法给赋值
s.setName("林青霞");
s.setAge(27);
System.out.println(s.getName()+"---"+s.getAge());
}
}
6.this关键字
this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。
注意:谁调用这个方法,在该方法内部的this就代表谁。
this的场景:
解决局部变量隐藏成员变量
例子
===================================================================
class Student {
private String name;
public String getName() {
return name;
/*public void setName(String n)
{
name = n;//不用this关键字的以前用法,但是s的名字不够鲜明于是改为name
}*/
public void setName(String name) { //name = "林青霞";
//name = name; //变量的使用规则:就近原则
//这里是类名,目前还没有说过类似的用法,所以这个是有问题的
//这里的调用只能通过对象名
//这个对象如果存在,它应该代表的是Student的一个对象。
//那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this
//Student.name = name;
this.name = name;
}
}
class StudentTest {
public static void main(String[] args) {
//创建学生对象
Student s = new Student();
//给成员变量赋值
s.setName("林青霞");
System.out.println(s.getName());
}
}
==================================================================================
this:哪个对象调用那个方法,this就代表那个对象
this关键字的内存图解.bmp
7.构造方法
构造方法:
给对象的数据进行初始化
格式:
A:方法名与类名相同
B:没有返回值类型,连void都没有
C:没有具体的返回值
例子
class Student {
public Student() {
System.out.println("这是构造方法");
}
}
class ConstructDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
System.out.println(s); //Student@e5bbd6
}
}
构造方法的注意事项:
A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
例子:
class Student
{
}
class ConstructDemo2
{
public static void main(String[] args)
{
//创建对象
Student s = new Student();
}
}
图解反编译前
反编译后
通过反编译可知
主要是new Student()引发的构造方法Student(反编译中的图解)public 为默认所以上图不显示
B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。(构造方法也可以重载,即带不同参数--默认不带参数)
注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法
8.
类的组成:成员变量,成员方法
今天我们又加入了一个新的成员:构造方法。
以后再提类的组成:
成员变量
构造方法
成员方法
图解
9.注意:
import必须出现在所有的class前面。
例如
10.static
static的特点:(它可以修饰成员变量,还可以修饰成员方法)
A:随着类的加载而加载
回想main方法。
B:优先于对象存在
C:被类的所有对象共享
举例:咱们班级的学生应该共用同一个班级编号。
其实这个特点也是在告诉我们什么时候使用静态?
如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
举例:
饮水机(用静态修饰)(饮水机可以多人共享使用)
水杯(不能用静态修饰)(水杯只能自己一个人用,原则上不可以共享,每个人都有一个)
D:可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般我们称其为:与类相关的,类成员
静态变量也可以通过类名调用.png
class Student {
//非静态变量
int num = 10;
//静态变量
static int num2 = 20;
}
class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.num);
System.out.println(Student.num2);
System.out.println(s.num2);
}
}
static的内存图解
11.static关键字注意事项
A:在静态方法中是没有this关键字的
如何理解呢?
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
B:静态方法只能访问静态的成员变量和静态的成员方法
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
简单记:
静态只能访问静态。(非静态可以访问一切)
例子
12.静态变量和成员变量的区别
所属不同
静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)
内存中位置不同
静态变量存储于方法区的静态区
成员变量存储于堆内存
内存出现时间不同
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
调用不同
静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用
13.
main方法的格式讲解:
public static void main(String[] args) {...}
public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。
static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。
void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。
main:是一个常见的方法入口。我见过的语言都是以main作为入口。
String[] args:这是一个字符串数组。值去哪里了?
这个东西到底有什么用啊?怎么给值啊?
这个东西早期是为了接收键盘录入的数据的。
格式是:
java MainDemo hello world java
例子
补充:
private是封装的一种表现。
思考题:构造方法中可不可以有return语句呢?
可以。而是写成这个样子:return;
day08
1.首先要注意,在同一个文件夹下,类定义在两个文件中和定义在一个文件中其实一样的。
2.例子
===========================================================================
class ArrayTool {
//把构造方法私有,外界就不能在创建对象了
private ArrayTool(){}
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
}
=====================================================
class ArrayDemo {
public static void main(String[] args) {
//定义数组
int[] arr = {28,55,37,46,19};
//需求:遍历数组
/*
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
*/
//如果我有多个数组都要进行遍历,那么,代码的重复度就很高
//如何改进呢?用方法改进
//调用
//静态方法
//printArray(arr);
//非静态方法
//ArrayDemo ad = new ArrayDemo();
//ad.printArray(arr);
//测试类的作用:创建其他类的对象,调用其他类的功能。
//而我们现在的操作是跟数组相关的,所以,你应该把这些操作定义到数组操作类中
//定义一个数组的操作类
//有了数组操作类之后的调用
//ArrayTool at = new ArrayTool();
//at.printArray(arr);
//方法改进为静态后,就可以直接通过类名调用
ArrayTool.printArray(arr);
}
/*
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
*/
//假设该方法不是静态的
/*
public void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
*/
}
=======================================================================
3.***文档注释,文档说明书
注意:如何***一个说明书呢?
A:写一个工具类
B:对这个类加入文档注释
怎么加呢?
加些什么东西呢?
C:用工具解析文档注释
javadoc工具
D:格式
javadoc -d 目录 -author -version ArrayTool.java
目录:就可以写一个文件夹的路径
***帮助文档出错:
找不到可以文档化的公共或受保护的类:告诉我们类的权限不够(解决办法:在class前面加public)
实例
=================================================================================
/**
* 这是针对数组进行操作的工具类
* @author 刘意
* @version V.10
*/
public class ArrayTool {
//把构造方法私有,外界就不能在创建对象了
/**
* 这是私有构造
*/
private ArrayTool(){}
/**
* 这是遍历数组的方法,遍历后的格式是:[元素1, 元素2, 元素3, ...]
* @param arr 这是要被遍历的数组
*/
public static void printArray(int[] arr) {
System.out.print("[");
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+", ");
}
}
}
/**
* 这是获取数组中最大值的方法
* @param arr 这是要获取最大值的数组
* @return 返回数组中的最大值
*/
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;
}
/**
* 获取指定元素在数组中第一次出现的索引,如果元素不存在,就返回-1
* @param arr 被查找的数组
* @param value 要查找的元素
* @return 返回元素在数组中的索引,如果不存在,返回-1
*/
public static int getIndex(int[] arr,int value) {
int index = -1;
for(int x=0; x<arr.length; x++) {
if(arr[x] == value) {
index = x;
break;
}
}
return index;
}
}
==========================================================================================
4.如何查看API帮助文档
1:打开帮助文档
2:点击显示,找到索引,看到输入框
3:知道你要找谁?以Scanner举例
4:在输入框里面输入Scanner,然后回车
5:看包
java.lang包下的类不需要导入,其他的全部需要导入。
要导入:
java.util.Scanner
6:再简单的看看类的解释和说明,别忘了看看该类的版本
7:看类的结构
成员变量 字段摘要
构造方法 构造方法摘要
成员方法 方法摘要
8:学习构造方法
A:有构造方法 就创建对象
B:没有构造方法 成员可能都是静态的
9:看成员方法
A:左边
是否静态:如果静态,可以通过类名调用
返回值类型:人家返回什么,你就用什么接收。
B:右边
看方法名:方法名称不要写错
参数列表:人家要什么,你就给什么;人家要几个,你就给几个
实例
Math
Math:类包含用于执行基本数学运算的方法
由于Math类在java.lang包下,所以不需要导包。
特点:
没有构造方法,因为它的成员全部是静态的。
掌握一个方法:
获取随机数
public static double random():返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。
===========================================
class MathDemo {
public static void main(String[] args) {
//获取一个随机数
//double d = Math.random();
//System.out.println(d);
//需求:我要获取一个1-100之间的随机数,肿么办?
for(int x=0; x<100; x++) {
int number = (int)(Math.random()*100)+1;
System.out.println(number);
}
}
}
========================
5.代码块
局部代码块:局部位置,用于限定变量的生命周期
实例
构造代码块:在类中的成员位置,用{}括起来的代码
特点:每次调用构造方法执行前,都会先执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起。
class Code
{
//构造代码块
{
//注意这一段外面不加大括号会报错,加大括号后就不报错
int x = 100;
System.out.println(x);
}
public Code()
{
System.out.println("code");//这个打印语句在第三个也就是最后一个才输出
}
{
int y = 200;
System.out.println(y);
}
}
class CodeDemo
{
public static void main(String[] args)
{
Code c = new Code();//每一次调用构造方法,都会先执行构造代码块,然后才执行构造方法里面的内容
}
}
静态代码块:在类中的成员位置用{}括起来的代码。只不过它用static修饰了
作用:一般是对类进行初始化(随着类的加载而加载)
class Code
{
//静态代码块
static
{
int a = 1000;
System.out.println(a);
}
//构造代码块
{
int x = 10;
System.out.println(x);
}
//静态代码块
static
{
int b = 2000;
System.out.println(b);//执行顺序是:先打印a(1000),再打印b(2000),最后才打印x(10)
}
}
由上图可以知道,1000只打印了一次,说明静态代码块只执行一次。
面试题:
静态代码块,构造代码块,构造方法的执行顺序?
静态代码块 --- 构造代码块 --- 构造方法
而且:静态代码块:只执行一次
构造代码块:每次调用构造方法都执行
由上图可知静态代码块只执行一次,第二次new Student()的时候不打印静态代码块
6.继承 extend
好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类之间产生了关系,是多态的前提
类与类产生了关系,其实也是继承的一个弊端:
类的耦合性增强了。
开发的原则:低耦合,高内聚。
耦合:类与类的关系
内聚:就是自己完成某件事情的能力
注意:Java不支持多继承,但支持多层继承
Java中继承的特点:
A:Java只支持单继承,不支持多继承。
有些语言是支持多继承,格式:extends 类1,类2,...
B:Java支持多层继承(继承体系)
class Father {}
class Mother {}
class Son exnteds Father {} //正确的
class Son extends Father,Mother {} // 错误的
Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
并且子类可以直接使用父类的父类的方法
例子
class GrandFather {
public void show() {
System.out.println("我是爷爷");
}
}
class Father extends GrandFather {
public void method(){
System.out.println("我是老子");
}
}
class Son extends Father {}
class ExtendsDemo2 {
public static void main(String[] args) {
Son s = new Son();
s.method(); //使用父亲的
s.show(); //使用爷爷的
}
}
7.继承的注意事项:
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)(也就是说,父类带private的方法,变量都不可以访问)
B:子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
C:不要为了部分功能而去继承
什么时候考虑使用继承呢?
继承其实体现的是一种关系:"is a"。
Person
Student
Teacher
水果
苹果
香蕉
橘子
采用假设法。
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
8.类的组成:
成员变量:
构造方法:
成员方法:
类的组成部分的各自关系。
继承中成员变量的关系:
A:子类中的成员变量和父类中的成员变量名称不一样
B:子类中的成员变量和父类中的成员变量名称一样
在子类方法中访问一个变量的查找顺序:
a:在子类方法的局部范围找,有就使用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就使用
d:如果还找不到,就报错。
示例程序
好了,问题来了,我不仅仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?(用this)
办法(修改于上一个程序)
public void show() {
int num = 30;
System.out.println(num);//就近原则num=30
System.out.println(this.num);//本类中的num=20
}
如果还想要输出父类成员范围的num。怎么办呢
super关键字
public void show() {
int num = 30;
System.out.println(num);//30
System.out.println(super.num);//父类num=10
}
总结
public void show() {
int num = 30;
System.out.println(num);//局部num
System.out.println(this.num);//本类num
System.out.println(super.num);//父类num
}
9.this和super的区别
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
怎么用呢?
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
10.继承中构造方法的关系
A:子类中所有的构造方法默认都会访问父类中空参数的构造方法
B:为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
注意:子类每一个构造方法的第一条语句默认都是:super();
如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
报错。
如何解决呢?
A:在父类中加一个无参构造方法
B:通过使用super关键字去显示的调用父类的带参构造方法
C:子类通过this去调用本类的其他构造方法
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意事项:
this(...)或者super(...)必须出现在第一条语句上。
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。
(第一条语句给不给它都默认有一个空的super语句,最好手动说明以免引起冲突)
11.一个类的初始化过程
成员变量进行初始化
默认初始化
显示初始化
构造方法初始化
看程序写结果
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 构造代码块 > 构造方法
B:静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化
运行结果是:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
*/
12. A:成员变量的问题
int x = 10; //成员变量是基本类型
Student s = new Student(); //成员变量是引用类型
B:一个类的初始化过程
成员变量的初始化
默认初始化
显示初始化
构造方法初始化
C:子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化。
结果:
YXYZ
问题:
虽然子类中构造方法默认有一个super()
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。
例子
13.方法重写:子类中出现了和父类中方法声明一模一样的方法。
方法重载:
本类中出现的方法名一样,参数列表不同的方法。与返回值无
子类对象调用方法的时候:
先找子类本身,再找父类。
方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。
例子
A:定义一个手机类。
B:通过研究,我发明了一个新手机,这个手机的作用是在打完电话后,可以听天气预报。
class Phone {
public void call(String name) {
System.out.println("给"+name+"打电话");
}
}
class NewPhone extends Phone {
public void call(String name) {
//System.out.println("给"+name+"打电话");
super.call(name); //避免重复代码
System.out.println("可以听天气预报了");
}
}
class ExtendsDemo9 {
public static void main(String[] args) {
NewPhone np = new NewPhone();
np.call("林青霞");
}
}
14.方法重写的注意事项
A:父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
B:子类重写父类方法时,访问权限不能更低(public 高)
最好就一致
C:父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中讲解
子类重写父类方法的时候,最好声明一模一样。
15.两个面试题
1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写:
在子类中,出现和父类中一模一样的方法声明的现象。
方法重载:
同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值类型,因为它和返回值类型无关。
Override:方法重写
Overload:方法重载
2:this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this:代表当前类的对象引用
super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)
场景:
成员变量:
this.成员变量
super.成员变量
构造方法:
this(...)
super(...)
成员方法:
this.成员方法
super.成员方法
16.super
实例
//定义人类
class Person {
//姓名
private String name;
//年龄
private int age;
public Person() {
}
public Person(String name,int age) { //"林青霞",27
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//定义学生类
class Student extends Person {
public Student() {}
public Student(String name,int age) { //"林青霞",27
//this.name = name;
//this.age = age;
super(name,age);
}
}
class ExtendsTest4 {
public static void main(String[] args) {
//创建学生对象并测试
//方式1
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(27);
System.out.println(s1.getName()+"---"+s1.getAge());
//方式2
Student s2 = new Student("林青霞",27);
System.out.println(s2.getName()+"---"+s2.getAge());
}
补充笔记
API(Application Programming Interface)
应用程序编程接口(帮助文档)
day09
1.final引入
继承的代码体现
由于继承中方法有一个现象:方法重写。
所以,父类的功能,就会被子类给覆盖调。
有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
这个时候,针对这种情况,Java就提供了一个关键字:final
final:最终的意思。常见的是它可以修饰类,方法,变量。
2.final
final可以修饰类,方法,变量
特点:
final可以修饰类,该类不能被继承。
final可以修饰方法,该方法不能被重写。(覆盖,复写)
final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。
常量:
A:字面值常量
"hello",10,true
B:自定义常量
final int x = 10;
3.final面试题
4.final修饰变量的初始化时机
A:被final修饰的变量只能赋值一次。
B:在构造方法完毕前。(非静态的常量)
5.多态
多态概述
某一个事物,在不同时刻表现出来的不同状态。
通过猫这个小动物,说猫可以被称为猫,也可以被称为动物。在不同时刻,猫表现出的不同状态,来说明多态.
举例:
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。
动物 d = new 猫();
多态:同一个对象(事物),在不同时刻体现出来的不同状态。
举例:
猫是猫,猫是动物。
水(液体,固体,气态)。
多态的前提:
A:要有继承关系。
B:要有方法重写。
有父类引用指向子类对象
5. 多态中的成员访问特点:
A:成员变量
编译看左边,运行看左边。(意思是编译和运行都是看父类的,都是访问父类的成员,而变量不存在重写,父类的变量不会被子类覆盖)
B:构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
C:成员方法
编译看左边,运行看右边。(方法存在覆盖,存在方法重写,父类的方法被子类覆盖)
D:静态方法
编译看左边,运行看左边。(父类的静态方法不会被子类的静态方法所覆盖)
(静态和类相关,算不上重写,所以,访问还是左边的)
由于成员方法存在方法重写,所以它运行看右边。
完整代码
class Fu {
public int num = 100;
public void show() {
System.out.println("show Fu");
}
public static void function() {
System.out.println("function Fu");
}
}
class Zi extends Fu {
public int num = 1000;
public int num2 = 200;
public void show() {
System.out.println("show Zi");
}
public void method() {
System.out.println("method zi");
}
public static void function() {
System.out.println("function Zi");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
//要有父类引用指向子类对象。
//父 f = new 子();
Fu f = new Zi();
System.out.println(f.num);
//找不到符号
//System.out.println(f.num2);
f.show();
//找不到符号
//f.method();
f.function();
}
}
6.
多态的好处:
A:提高了代码的维护性(继承保证)
B:提高了代码的扩展性(由多态保证)
例子(来源网上)
7.多态的弊端:
不能使用子类的特有功能。(因为编译左边)
Fu f = new Zi();//f不能调用Fu中没有而Zi特有的功能
想使用子类的特有功能?行不行?
行。
怎么用呢?
A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)
对象间的转型问题:
向上转型:
Fu f = new Zi();
向下转型:
Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
实例
class Fu {
public void show() {
System.out.println("show fu");
}
}
class Zi extends Fu {
public void show() {
System.out.println("show zi");
}
public void method() {
System.out.println("method zi");
}
}
class DuoTaiDemo4 {
public static void main(String[] args) {
//测试
Fu f = new Zi();
f.show();
//f.method();
//创建子类对象,太占内存
//Zi z = new Zi();
//z.show();
//z.method();
//你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
//如果可以,但是如下
Zi z = (Zi)f;//强制类型转换
z.show();
z.method();
}
}
多态继承中的内存图解
多态中的对象变化内存图解
ClassCastException:类型转换异常
一般在多态的向下转型中容易出现
8.多态案例
9.抽象类的概述:
动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。
我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。
抽象类的特点:
A:抽象类和抽象方法必须用abstract关键字修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
C:抽象类不能实例化
因为它不是具体的。
抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
用于子类访问父类数据的初始化
D:抽象的子类
a:如果不想重写抽象方法,该子类是一个抽象类。
b:重写所有的抽象方法,这个时候子类是一个具体的类。
抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
Animal a = new Cat();
实例
//abstract class Animal //抽象类的声明格式
abstract class Animal {
//抽象方法
//public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
public abstract void eat();
public Animal(){} //构造器
}
//子类是抽象类
abstract class Dog extends Animal {}
//子类是具体类,重写抽象方法
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
class AbstractDemo {
public static void main(String[] args) {
//创建对象
//Animal是抽象的; 无法实例化
//Animal a = new Animal();
//通过多态的方式
Animal a = new Cat();
a.eat();
}
}
10. 抽象类的成员特点:
成员变量:既可以是变量,也可以是常量。
构造方法:有。
用于子类访问父类数据的初始化。
成员方法:既可以是抽象的,也可以是非抽象的。
抽象类的成员方法特性:
A:抽象方法 强制要求子类做的事情。
B:非抽象方法 子类继承的事情,提高代码复用性。
例子
11.体现多态的例子
abstract class Teacher {
//姓名
private String name;
//年龄
private int age;
public Teacher() {}
public Teacher(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象方法
public abstract void teach();
}
//基础班老师类
class BasicTeacher extends Teacher {
public BasicTeacher(){}
public BasicTeacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("基础班老师讲解JavaSE");
}
}
//就业班老师类
class WorkTeacher extends Teacher {
public WorkTeacher(){}
public WorkTeacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("就业班老师讲解JavaEE");
}
}
class AbstractTest2 {
public static void main(String[] args) {
//具体的类测试,自己玩
//测试(多态)
//基础班老师
Teacher t = new BasicTeacher();
t.setName("刘意");
t.setAge(30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
t = new BasicTeacher("刘意",30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
//就业班老师
t = new WorkTeacher();
t.setName("林青霞");
t.setAge(27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
t = new WorkTeacher("林青霞",27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
}
}
上述程序的t被多次使用作很多用途,体现了一个t 的多态
12.多态小问题
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
A:可以。
B:不让创建对象。
abstract不能和哪些关键字共存?
private 冲突(private要求不能重写,而abstract要求重写)
final 冲突
static 无意义
13.接口
接口的特点
接口的特点:
A:接口用关键字interface表示
interface 接口名 {}
B:类实现接口用implements表示
class 类名 implements 接口名 {}
C:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式来实例化。
D:接口的子类
a:可以是抽象类。但是意义不大。
b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用)
C:接口多态(最常用)
实例
//定义动物培训接口
interface AnimalTrain {
public abstract void jump();
}
//抽象类实现接口
abstract class Dog implements AnimalTrain {
}
//具体类实现接口
class Cat implements AnimalTrain {
public void jump() {
System.out.println("猫可以跳高了");
}
}
class InterfaceDemo {
public static void main(String[] args) {
//AnimalTrain是抽象的; 无法实例化
//AnimalTrain at = new AnimalTrain();
//at.jump();
AnimalTrain at = new Cat();
at.jump();
}
}
接口的变量默认是常量
接口的变量默认是静态的
14.接口成员特点
成员变量;只能是常量,并且是静态的。
默认修饰符:public static final
建议:自己手动给出。
构造方法:接口没有构造方法。
成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。
所有的类都默认继承自一个类:Object。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。
实例
interface Inter {
public int num = 10;
public final int num2 = 20;
public static final int num3 = 30;
//错误: 需要<标识符>
//public Inter() {}
//接口方法不能带有主体
//public void show() {}
//abstract void show(); //默认public
public void show(); //默认abstract
}
//接口名+Impl这种格式是接口的实现类格式
/*
class InterImpl implements Inter {
public InterImpl() {
super();
}
}
*/
class InterImpl extends Object implements Inter {
public InterImpl() {
super();
}
public void show() {}
}
//测试类
class InterfaceDemo2 {
public static void main(String[] args) {
//创建对象
Inter i = new InterImpl();
System.out.println(i.num);
System.out.println(i.num2);
//i.num = 100;
//i.num2 = 200;
//System.out.println(i.num); //无法为最终变量num分配值
//System.out.println(i.num2);//无法为最终变量num2分配值
System.out.println(Inter.num);
System.out.println(Inter.num2);
System.out.println("--------------");
}
}
15.类与类,类与接口,接口与接口的关系
类与类:
继承关系,只能单继承,可以多层继承。 层与层之间还是单继承。
类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。
接口与接口:
继承关系,可以单继承,也可以多继承。(也就是说,java的类只能单继承,但是java的接口可以多继承)
例子
interface Father {
public abstract void show();
}
interface Mother {
public abstract void show2();
}
interface Sister extends Father,Mother {
}
//class Son implements Father,Mother //多实现
class Son extends Object implements Father,Mother {
public void show() {
System.out.println("show son");
}
public void show2() {
System.out.println("show2 son");
}
}
class InterfaceDemo3 {
public static void main(String[] args) {
//创建对象
Father f = new Son();
f.show();
//f.show2(); //报错
Mother m = new Son();
//m.show(); //报错
m.show2();
}
}
16.抽象类和接口的区别:
A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承
C:设计理念区别
抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。(相当于USB插口,可以插上东西实现扩展功能)
补充笔记
多态的分类:
a:具体类多态
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
b:抽象类多态
abstract class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
c:接口多态
interface Fu {}
class Zi implements Fu {}
Fu f = new Zi();
(2)抽象类的特点
A:抽象类和抽象方法必须用关键字abstract修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
C:抽象类不能实例化
D:抽象类的子类
a:是一个抽象类。
b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。
抽象类的几个小问题
A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
用于子类访问父类数据的初始化
B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
为了不让创建对象
day10
1.形式参数
基本类型(太简单,不是我今天要讲解的)
引用类型
类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
抽象类:需要的是该抽象的类子类对象
接口:需要的是该接口的实现类对象
抽象类形式参数举例
===============================
abstract class Person {
public abstract void study();
}
class PersonDemo {
public void method(Person p) {//p; p = new Student(); Person p = new Student(); //多态
p.study();
}
}
//定义一个具体的学生类
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest {
public static void main(String[] args) {
//目前是没有办法的使用的
//因为抽象类没有对应的具体类
//那么,我们就应该先定义一个具体类
//需求:我要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
}
}
===========================================================
接口形式参数举例//在这里跟抽象类有点相似
====================================
//定义一个爱好的接口
interface Love {
public abstract void love();
}
class LoveDemo {
public void method(Love l) { //l; l = new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}
//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println("老师爱学生,爱Java,爱林青霞");
}
}
class TeacherTest {
public static void main(String[] args) {
//需求:我要测试LoveDemo类中的love()方法
LoveDemo ld = new LoveDemo();
Love l = new Teacher();
ld.method(l);
}
}
2.返回值类型
基本类型:(基本类型太简单,我不准备讲解)
引用类型:
类:返回的是该类的对象
抽象类:返回的是该抽象类的子类对象
接口:
返回类型是类举例
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
//Student s = new Student();
//Student ss = s;
//Student s = new Student();
//return s;
return new Student();
}
}
class StudentTest2 {
public static void main(String[] args) {
//需求:我要使用Student类中的study()方法
//但是,这一次我的要求是,不要直接创建Student的对象
//让你使用StudentDemo帮你创建对象
StudentDemo sd = new StudentDemo();
Student s = sd.getStudent(); //new Student(); Student s = new Student();
s.study();
}
}
返回类型是抽象类举例
abstract class Person {
public abstract void study();
}
class PersonDemo {
public Person getPerson() {
//Person p = new Student();
//return p;
return new Student();
}
}
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest2 {
public static void main(String[] args) {
//需求:我要测试Person类中的study()方法
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //new Student(); Person p = new Student(); 多态
p.study();
}
}
接口同理
3.链式编程
/*
链式编程。
每次调用完毕方法后,返回的是一个对象。
*/
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
return new Student();
}
}
class StudentTest3 {
public static void main(String[] args) {
//如何调用的呢?
StudentDemo sd = new StudentDemo();
//Student s = sd.getStudent();
//s.study();
//链式编程
sd.getStudent().study();
}
}
4.包
A:其实就是文件夹
B:作用
a:把相同的类名放到不同的包中
b:对类进行分类管理
举例
学生:增加,删除,修改,查询
老师:增加,删除,修改,查询
方案1:按照功能分
cn.itcast.add
AddStudent
AddTeacher
cn.itcast.delete
DeleteStudent
DeleteTeacher
cn.itcast.update
UpdateStudent
UpdateTeacher
cn.itcast.find
FindStudent
FindTeacher
方案2:按照模块分
cn.itcast.teacher
AddTeacher
DeleteTeacher
UpdateTeacher
FindTeacher
cn.itcast.student
AddStudent
DeleteStudent
UpdateStudent
FindStudent
包的定义
package 包名;
多级包用.分开即可
注意事项:
A:package语句必须是程序的第一条可执行的代码
B:package语句在一个java文件中只能有一个
C:如果没有package,默认表示无包名
5.带包的编译和运行:
A:手动式
a:编写一个带包的java文件。
b:通过javac命令编译该java文件。
c:手动创建包名。
d:把b步骤的class文件放到c步骤的最底层包
e:回到和包根目录在同一目录的地方,然后运行
带包运行。
B:自动式
a:编写一个带包的java文件。
b:javac编译的时候带上-d即可
javac -d . HelloWorld.java
(注意不要漏掉点号)
c:回到和包根目录在同一目录的地方,然后运行
带包运行。
6.导包:
格式:import 包名;
这种方式导入是到类的名称。
注意:我们用谁就导谁。(尽量少用星号*)
面试题:
package,import,class有没有顺序关系?
有。
package > import > class
Package:只能有一个
import:可以有多个
class:可以有多个,以后建议是一个
7.权限修饰符:
8.修饰符:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
除此以外的组合规则:
成员变量:public static final
成员方法:public static
public abstract
public final
9.内部类
内部类概述:
把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
内部的访问特点:
A:内部类可以直接访问外部类的成员,包括私有。
B:外部类要访问内部类的成员,必须创建对象。
*/
class Outer {
private int num = 10;
class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
//找不到符号
//show();
Inner i = new Inner();
i.show();
}
}
class InnerClassDemo {
public static void main(String[] args) {
}
}
10.
内部类位置
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。
成员位置:在成员位置定义的类,被称为成员内部类。
class Outer {
private int num = 10;
//成员位置
/*
class Inner {
}
*/
public void method() {
//局部位置
class Inner {
}
}
}
class InnerClassDemo2 {
public static void main(String[] args) {
}
}
11.成员内部类:
如何直接访问内部类的成员。
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
例子
class Outer {
private int num = 10;
class Inner {
public void show() {
System.out.println(num);
}
}
}
class InnerClassDemo3 {
public static void main(String[] args) {
//需求:我要访问Inner类的show()方法
//Inner i = new Inner();
//i.show();
//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
12.成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰。
案例:我有一个人(人有身体,身体内有心脏。)
class Body {
private class Heart {
public void operator() {
System.out.println("心脏搭桥");
}
}
public void method() {
if(如果你是外科医生) {
Heart h = new Heart();
h.operator();
}
}
}
按照我们刚才的讲解,来使用一下
Body.Heart bh = new Body().new Heart();
bh.operator();
//加了private后,就不能被访问了,那么,怎么玩呢?
Body b = new Body();
b.method();
例子
===============================================
class Outer {
private int num = 10;
private static int num2 = 100;
//内部类用静态修饰是因为内部类可以看出是外部类的成员
public static class Inner {
public void show() {
//System.out.println(num);
System.out.println(num2);
}
public static void show2() {
//System.out.println(num);
System.out.println(num2);
}
}
}
class InnerClassDemo4 {
public static void main(String[] args) {
//使用内部类
// 限定的新静态类
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
//oi.show2();
//成员内部类被静态修饰后的访问方式是:
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
oi.show();
oi.show2();
//show2()的另一种调用方式
Outer.Inner.show2();
}
}
===========================================================
13.面试题
注意:
1:内部类和外部类没有继承关系。
2:通过外部类名限定this对象
Outer.this
14.局部内部类
局部内部类
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
面试题:
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须用final修饰
B:为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。(个人理解,也就是说,不会立刻消失的method方法已经无法知道它的内部类的方法中的num2究竟是什么来的,毕竟num2已逝去)
而堆内存的内容并不会立即消失。所以,我们加final修饰。
加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
我在内存中存储的是数据20,所以,我还是有数据在使用。
(这个可以用xjad软件反编译理解)
例子
===============================
=============================================================
15.匿名内部类
匿名内部类
就是内部类的简化写法。
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:
new 类名或者接口名(){
重写方法;
}
本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。(再次强调,是子类匿名对象,子类!)
当里面有两个方法时,如何调用?
完整代码
代码解析
完整代码对比
interface Person {
public abstract void study();
}
class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}
//实现类
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}
16.匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
========================================================
interface Inter {
void show();
//public abstract
}
class Outer {
//补齐代码
public static Inter method() {
//子类对象 -- 子类匿名对象
return new Inter() {
public void show() {
System.out.println("HelloWorld");
}
};
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
/*
1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
2:Outer.method().show()可以看出method()方法的返回值是一个对象。
又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
*/
}
}
day10补充笔记
链式编程
对象.方法1().方法2().......方法n();
这种用法:其实在方法1()调用完毕后,应该一个对象;
方法2()调用完毕后,应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象。
day01
win 7系统打开DOS有趣方法:按住shift+右键,单击“在此处打开命令窗口”(注意:在此处可以是任何的文件夹,不一定是桌面)
用DOS删除的文件不可以在回收站恢复?!!
常用DOS命令
d: 回车 盘符切换
dir(directory):列出当前目录下的文件以及文件夹
md (make directory) : 创建目录(创建文件夹)
rd (remove directory): 删除目录(删除文件夹,注意:前提是文件夹必须是空的!!)
如果想删除不是空的文件夹(比如删除aaaaa文件夹),可以用命令 rd /s aaaaa(会有删除提示)或者rd /s /q aaaaa(静默删除)
cd (change directory)改变指定目录(进入指定目录)
cd.. : 退回到上一级目录
cd\: 退回到根目录
del (delete): 删除文件,删除一堆后缀名一样的文件*.txt
exit : 退出dos命令行
cls : (clear screen)清屏
第一个程序:HelloWorld案例(掌握)
class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
(1)程序解释:
A:Java程序的最基本单位是类,所以我们要定义一个类。
格式:class 类名
举例:class HelloWorld
B:在类中写内容的时候,用大括号括起来。
C:Java程序要想执行,必须有main方法。
格式:public static void main(String[] args)
D:要指向那些东西呢,也用大括号括起来。
E:你要做什么呢?今天我们仅仅做了一个简单的输出
格式:System.out.println("HelloWorld");
注意:""里面的内容是可以改动的。
(2)Java程序的开发执行流程:
A:编写java源程序(.java)
B:通过javac命令编译生成.class文件
C:通过java命令运行.class文件
常见的问题(掌握)
(1)扩展名被隐藏
如何找到:工具--文件夹选项--查看--去除隐藏扩展名的那个勾勾
(2)要求文件名称和类名一致。
实际上不这样做也是可以的。
但是,注意:
javac后面跟的是文件名+扩展名
java后面跟的类名不带扩展名
(3)Java语言严格区分大小写,请注意。
还有就是单词不要写错了。
(4)见到非法字符: \65307肯定是中文问题。
写程序要求标点符号必须全部是英文状态。
(5)括号的配对问题。
一般来说,括号都是成对出现的。
(6)遇到
在类 HelloWorld 中找不到主方法, 请将主方法定义为
肯定是主方法的格式问题。
path环境变量
path环境变量的作用
保证javac命令可以在任意目录下运行。
同理可以配置qq等
day2
1.java关键字--组成关键字的字母全部小写
注意:goto和const作为保留字存在,目前并不使用(在JDK的新版本中可能提升为关键字)
2.demo:案例,演示
3.Java标识符
可以是
英文大小写字母
数字字符
$和_
注意:
A.不能以数字开头
B.不能是Java中的关键字
C.Java语言严格区分大小写
4.常见的命名规则(重点):见名知意
举例:我要定义一个学生类
class Student {}
class S{}
包:其实就是文件夹,用于把相同的类名进行区分
全部小写
单级:liuyi
多级:cn.itcast(解析:cn是一个文件夹,itcast也是一个文件夹,cn文件夹里包含有itcast文件夹)
cn
itcast
类或者接口:
一个单词:单词的首字母必须大写
举例:Student,Dog
多个单词:每个单词的首字母必须大写
举例:HelloWorld,StudentName
方法或者变量:
一个单词:单词的首字母小写
举例:main,age
多个单词:从第二个单词开始,每个单词的首字母大写
举例:studentAge,showAllNames()
常量:
一个单词:全部大写
举例:PI
多个单词:每个字母都大写,用_隔开
举例:STUDENT_MAX_AGE
5.Java中注释的分类及格式
单行注释://
多行注释:/星 星/
注意:多行不可以嵌套使用,而单行是可以的
文档注释:被javadoc工具解析生成一个说明书
用注释写的一个Java案例
===========================华丽的分割线=========================================
/*
需求:我准备写一个java程序,把“HelloWorld”这句话输出在控制台
分析:A:要写一个java程序,必须定义类
B:把数据能够输出,说明我们的程序是可以独立运行的,而程序要独立运行,必须定义main方法
C:把数据输出在控制台,必须使用输出语句
实现:
A:java语言提供了一个关键字:class用来定义类,后面跟的是类名
B:main方法的格式是固定的:
public static void main(String[] args) {
}
C:输出语句的格式是固定的:
System.out.println("HelloWorld");
"HelloWorld"这个内容是可以改变的
*/
//这是我的HelloWorld案例
class HelloWorld {
/*
为了程序能够独立运行,定义main方法
main方法是程序的入口
被jvm自动调用
*/
public static void main(String[] args) {
//为了把数据显示在控制台,我们就使用了输出语句
System.out.println("HelloWorld");
}
}
===========================华丽的分割线=============================================
6.常量:
在程序执行过程中,其值不发生改变的量。
分类:
A:字面值常量
B:自定义常量(后面讲)
字面值常量
A:字符串常量 用双引号括起来的内容。
B:整数常量 所有的整数
举例:100, 200
C:小数常量 所有的小数
举例:10.23,110.11
D:字符常量 用单引号括起来的内容
举例:‘a’,‘A’,‘0’
错误的:‘ab’
E:布尔常量 比较特殊
举例:true,false
F:空常量 后面讲
举例:null
7.Java进制
Java针对整数常量提供了4种表现形式
二进制(jdk7以后有)
八进制
十进制
十六进制
8.快速的进制转换法
8421码,是bcd码一种。
它表达的意思是每一个二进制位上的数据对应一个固定的值,
只需要把对应的1位置的数据值给相加,即可得到该二进制对应的十进制的值
二进制 1 1 1 1 1 1 1 1
十进制 128 64 32 16 8 4 2 1
例
二进制到十进制的转换
1010100 = 64 + 16 + 4 = 84;
十进制到二进制的转换
100 = 0b1100100(对照着看,首先100<128,所以第八位为0;然后100>64,第七位为1;接着,100-64=36,36>32,所以第六位为1;然后,36-32=4,4<16,所以第五位为0;然后,4<8,第四位为0;然后,4=4,所以第三位为1;
然后,0<2,第二位为0;然后0<1,第一位为0,总的来说是01100100,去掉首位的0就是1100100,再规范化表示为0b1100100)
第一个程序:HelloWorld案例(掌握)
class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
(1)程序解释:
A:Java程序的最基本单位是类,所以我们要定义一个类。
格式:class 类名
举例:class HelloWorld
B:在类中写内容的时候,用大括号括起来。
C:Java程序要想执行,必须有main方法。
格式:public static void main(String[] args)
D:要指向那些东西呢,也用大括号括起来。
E:你要做什么呢?今天我们仅仅做了一个简单的输出
格式:System.out.println("HelloWorld");
注意:""里面的内容是可以改动的。
(2)Java程序的开发执行流程:
A:编写java源程序(.java)
B:通过javac命令编译生成.class文件
C:通过java命令运行.class文件
常见的问题(掌握)
(1)扩展名被隐藏
如何找到:工具--文件夹选项--查看--去除隐藏扩展名的那个勾勾
(2)要求文件名称和类名一致。
实际上不这样做也是可以的。
但是,注意:
javac后面跟的是文件名+扩展名
java后面跟的类名不带扩展名
(3)Java语言严格区分大小写,请注意。
还有就是单词不要写错了。
(4)见到非法字符: \65307肯定是中文问题。
写程序要求标点符号必须全部是英文状态。
(5)括号的配对问题。
一般来说,括号都是成对出现的。
(6)遇到
在类 HelloWorld 中找不到主方法, 请将主方法定义为
肯定是主方法的格式问题。
path环境变量
path环境变量的作用
保证javac命令可以在任意目录下运行。
同理可以配置qq等
day2
1.java关键字--组成关键字的字母全部小写
注意:goto和const作为保留字存在,目前并不使用(在JDK的新版本中可能提升为关键字)
2.demo:案例,演示
3.Java标识符
可以是
英文大小写字母
数字字符
$和_
注意:
A.不能以数字开头
B.不能是Java中的关键字
C.Java语言严格区分大小写
4.常见的命名规则(重点):见名知意
举例:我要定义一个学生类
class Student {}
class S{}
包:其实就是文件夹,用于把相同的类名进行区分
全部小写
单级:liuyi
多级:cn.itcast(解析:cn是一个文件夹,itcast也是一个文件夹,cn文件夹里包含有itcast文件夹)
cn
itcast
类或者接口:
一个单词:单词的首字母必须大写
举例:Student,Dog
多个单词:每个单词的首字母必须大写
举例:HelloWorld,StudentName
方法或者变量:
一个单词:单词的首字母小写
举例:main,age
多个单词:从第二个单词开始,每个单词的首字母大写
举例:studentAge,showAllNames()
常量:
一个单词:全部大写
举例:PI
多个单词:每个字母都大写,用_隔开
举例:STUDENT_MAX_AGE
5.Java中注释的分类及格式
单行注释://
多行注释:/星 星/
注意:多行不可以嵌套使用,而单行是可以的
文档注释:被javadoc工具解析生成一个说明书
用注释写的一个Java案例
===========================华丽的分割线=========================================
/*
需求:我准备写一个java程序,把“HelloWorld”这句话输出在控制台
分析:A:要写一个java程序,必须定义类
B:把数据能够输出,说明我们的程序是可以独立运行的,而程序要独立运行,必须定义main方法
C:把数据输出在控制台,必须使用输出语句
实现:
A:java语言提供了一个关键字:class用来定义类,后面跟的是类名
B:main方法的格式是固定的:
public static void main(String[] args) {
}
C:输出语句的格式是固定的:
System.out.println("HelloWorld");
"HelloWorld"这个内容是可以改变的
*/
//这是我的HelloWorld案例
class HelloWorld {
/*
为了程序能够独立运行,定义main方法
main方法是程序的入口
被jvm自动调用
*/
public static void main(String[] args) {
//为了把数据显示在控制台,我们就使用了输出语句
System.out.println("HelloWorld");
}
}
===========================华丽的分割线=============================================
6.常量:
在程序执行过程中,其值不发生改变的量。
分类:
A:字面值常量
B:自定义常量(后面讲)
字面值常量
A:字符串常量 用双引号括起来的内容。
B:整数常量 所有的整数
举例:100, 200
C:小数常量 所有的小数
举例:10.23,110.11
D:字符常量 用单引号括起来的内容
举例:‘a’,‘A’,‘0’
错误的:‘ab’
E:布尔常量 比较特殊
举例:true,false
F:空常量 后面讲
举例:null
7.Java进制
Java针对整数常量提供了4种表现形式
二进制(jdk7以后有)
八进制
十进制
十六进制
8.快速的进制转换法
8421码,是bcd码一种。
它表达的意思是每一个二进制位上的数据对应一个固定的值,
只需要把对应的1位置的数据值给相加,即可得到该二进制对应的十进制的值
二进制 1 1 1 1 1 1 1 1
十进制 128 64 32 16 8 4 2 1
例
二进制到十进制的转换
1010100 = 64 + 16 + 4 = 84;
十进制到二进制的转换
100 = 0b1100100(对照着看,首先100<128,所以第八位为0;然后100>64,第七位为1;接着,100-64=36,36>32,所以第六位为1;然后,36-32=4,4<16,所以第五位为0;然后,4<8,第四位为0;然后,4=4,所以第三位为1;
然后,0<2,第二位为0;然后0<1,第一位为0,总的来说是01100100,去掉首位的0就是1100100,再规范化表示为0b1100100)
9.原码反码补码
原码:
正数的原码最高位是0;
负数的原码最高位是1;
其他的是数值位。
符号位 数值位
+7 0 0000111
-7 1 0000111
反码:
正数的反码与原码相同。
负数的反码与原码是符号不变,数值位取反(0变1,1变0)
+7 0 0000111
-7 1 1111000
补码:
正数的补码与原码相同
负数的补码是在反码的基础上加1.
+7 0 0000111
-7 1 1111001
有符号数据表示法的练习
A:已知某数X的原码为10110100B,试求X的补码和反码。
符号位 数值位
原码: 10110100
反码: 11001011
补码: 11001100
B:已知某数X的补码11101110B,试求其原码。
符号位 数值位
补码: 11101110
反码: 11101101
原码: 10010010
10.数据类型:Java是一种强类型的语言,针对每一种数据都定义了明确的数据类型。
数据类型分类:
A:基本数据类型
B:引用数据类型(类,接口,数值)
基本数据类型:4类8种
A:整数 占用字节数
byte 1
short 2
int 4
long 8
B:浮点数
float 4
double 8
C:字符
char 2
D:布尔
boolean
1
注意:
整数默认是int类型
浮点数默认是double类型。
长整型后缀用L或者l标记。建议使用L。
例如
在Java中,
long j = 10000000000;
System.out.println(j);
编译时会报错 错误: 过大的整数: 10000000000,因为整数(这里是10000000000)默认是int类型
解决办法 long j = 10000000000L;
单精度浮点数用F或者f标记。建议使用F。
例如
在Java中,
float f = 12.345;
System.out.println(f);
编译时会报错 错误: 不兼容的类型: 从double转换到float可能会有损失
解决办法 float f = 12.345F;
11.数据类型转换
默认转换(从小到大的转换)
A:byte,short,char—int—long—float—double
B:byte,short,char相互之间不转换,他们参与运算首先转换为int类型
举例
=================================================================
byte a = 3;
int b = 4;
byte c = a + b;//有问题
int d = a + b;//没有问题
=================================================================
上述 byte c = a + b;//有问题
如何解决?用强制类型转换
12.强制转换:
从大的数据类型到小的数据类型。
格式:
目标数据类型 变量 = (目标数据类型) (被转换的数据);
注意:
不要随意的去使用强制转换,因为它隐含了精度损失问题。
那么,
//用强制类型转换改进
byte c = (byte) (a + b);
System.out.println(c);
13.思考题:看看下面两个定义有没有区别呢?
float f1 = (float)12.345;
float f2 = 12.345f;
f1其实是通过一个double类型转换过来的。
而f2本身就是一个float类型。(建议用f2的写法)
14.面试题
A面试题:
byte b1=3,b2=4,b;
b=b1+b2;
b=3+4;
哪句是编译失败的呢?为什么呢?
答:b = b1 + b2;是有问题的。
因为变量相加,会首先看类型问题,最终把结果赋值的也会考虑类型问题。
常量相加,首先做加法,然后看结果是否在赋值的数据类型范围内,如果不是,才报错。
也就是说。b = b1 + b2; -----这个是类型提升,所有有问题。b1 + b2首先整体提升为int类型(byte,short,char相互之间不转换,他们参与运算首先转换为int类型),int类型的(b1+b2)赋值给byte类型的b,所以有损失精度的错误。
b = 3 + 4; //常量,先把结果计算出来,然后看是否在byte的范围内,如果在就不报错。也就是说,编译器把3+4看做一个常量而不是变量的加法运算。所以不报错
15.强制转换数据溢出后的结果怎么算(一个实例)
byte b = 130;有没有问题?如果我想让赋值正确,可以怎么做?结果是多少呢?
//我们可以使用强制类型转换
byte b = (byte) 130;
//结果是多少呢?
System.out.println(b);
分析过程:
我们要想知道结果是什么,就应该知道是如何进行计算的。
而我们又知道计算机中数据的运算都是补码进行的。
而要得到补码,首先要计算出数据的二进制。
A:获取130这个数据的二进制。
00000000 00000000 00000000 10000010
这是130的原码,也是反码,还是补码。
B:做截取操作,截成byte类型的了。
10000010
这个结果是补码。
C:已知补码求原码。(注意不要漏掉这一步,因为内存中操作的是补码,而我们看到的是补码,所以还要转换成原码)
符号位 数值位
补码: 10000010
反码: 10000001
原码: 11111110
16.
//直接输出一个字符
System.out.println('a'); //输出a
//输出一个字符和一个整数做加法
System.out.println('a'+1); //输出98
ASCII码表。
记住三个值:
'a' 97
'A' 65
'0' 48注意
17.字符串参与运算
System.out.println("hello"+'a'+1); //输出helloa1,hello优先与‘a’结合
System.out.println('a'+1+"hello"); //输出98hello,‘a’优先与1结合,形成98再与hello结合
System.out.println("5+5="+5+5); //输出5+5=55,字符串与数字5先结合
System.out.println(5+5+"=5+5"); //输出10=5+5,5+5优先形成10,再与字符串结合
补:‘a’+1有类型提升???!
day3
1.在定义Long或者Float类型变量的时候,要加L或者f。
整数默认是int类型,浮点数默认是double。
byte,short在定义的时候,他们接收的其实是一个int类型的值。
这个是自己做了一个数据检测的,如果不再它们的范围内,就报错。
float表示的数据范围比long的范围要大
long:2^63-1
float:3.4*10^38 > 2*10^38 > 2*8^38 = 2*2^3^38 = 2*2^114 > 2^63-1
2.面试题:Java语言中的字符char可以存储一个中文汉字吗?为什么呢?
可以。因为java语言中的字符占用两个字节。(Java中char占两个字节,C语言中char占一个字节)
Java语言采用的是Unicode编码。
3.
A:整数相除只能得到整数。如果想得到小数,必须把数据变化为浮点数类型
B:/获取的是除法操作的商,%获取的是除法操作的余数
=========================================================================
System.out.println(x/y); //整数相除只能得到整数
//我就想得到小数,该肿么办呢?
//只需要把操作的数据中任意的一个数据变为浮点数
System.out.println(x*1.0/y);
//%的应用
System.out.println(x%y); //得到的是余数
==========================================================================
4.++,--运算符的使用
//参与运算使用
int a = 3;
int b = 4;
int c = a++;
int d = b--;
System.out.println("a:"+a); //输出为4
System.out.println("b:"+b); //输出为3
System.out.println("c:"+c); //输出为3
System.out.println("d:"+d); //输出为4
5.一个面试题
面试题:
short s=1;s = s+1;
short s=1;s+=1;
上面两个代码有没有问题,如果有,那里有问题。
class OperatorTest {
public static void main(String[] args) {
//short s = 1;
//s = s + 1;
//System.out.println(s);
short s = 1;
s += 1; //好像是 s = s + 1;
System.out.println(s);
}
}
为什么第二个木有问题呢?
扩展的赋值运算符其实隐含了一个强制类型转换。
s += 1;
不是等价于 s = s + 1;
而是等价于 s = (s的数据类型)(s + 1);
(个人理解)也就是说,s = s + 1中的s + 1包含了加法运算,short类型出现了提升(提升为int类型)
而s+=1本身隐含了强制的类型转换
6.逻辑运算符:
&,|,^,!
&&,||
特点:
逻辑运算符一般用于连接boolean类型的表达式或者值。
表达式:就是用运算符把常量或者变量连接起来的符合java语法的式子。
算术表达式:a + b
比较表达式:a == b
结论:
&逻辑与:有false则false。
|逻辑或:有true则true。
^逻辑异或:相同为false,不同为true。
举例:情侣关系。男男,男女,女男,女女
!逻辑非:非false则true,非true则false。
特点:偶数个不改变本身。
例如
int a = 3;
int b = 4;
int c = 5;
//&逻辑与
System.out.println((a > b) & (a > c)); //false & false = false
System.out.println((a > b) & (a < c)); //false & true = false
System.out.println((a < b) & (a > c)); //true & false = false
System.out.println((a < b) & (a < c)); //true & true = true
7.Java中&&与&
&&和&的区别? 同理||和|的区别?
A:最终结果一样。
B:&&具有短路效果。左边是false,右边不执行。
开发中常用的逻辑运算符:
&&,||,!
示例
//boolean b1 = ((x++ == 3) & (y++ == 4));
//boolean b1 = ((x++ == 3) && (y++ == 4));
//boolean b1 = ((++x == 3) & (y++ == 4));
boolean b1 = ((++x == 3) && (y++ == 4));
System.out.println("x:"+x);
System.out.println("y:"+y);
System.out.println(b1);
8.位运算符:
&,|,^,~
<<,>>,>>>
注意:
要做位运算,首先要把数据转换为二进制。
例子
int a = 3;
int b = 4;
System.out.println(3 & 4);
System.out.println(3 | 4);
System.out.println(3 ^ 4);
System.out.println(~3);
分析:因为是位运算,所以我们必须先把数据换算成二进制。
3的二进制:11
00000000 00000000 00000000 00000011
4的二进制:100
00000000 00000000 00000000 00000100
&位与运算:有0则0。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000000
结果是:0
|位或运算:有1则1。
00000000 00000000 00000000 00000011
|00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
^位异或运算:相同则0,不同则1。
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000100
-----------------------------------
00000000 00000000 00000000 00000111
结果是:7
~按位取反运算符:0变1,1变0
00000000 00000000 00000000 00000011
~11111111 11111111 11111111 11111100 (补码)
补码:11111111 11111111 11111111 11111100
反码:11111111 11111111 11111111 11111011
原码:10000000 00000000 00000000 00000100
结果是:-4
9.^的特点:一个数据位异或两次,该数本身不变。(^指的是异或运算符)
例如
int a = 10;
int b = 20;
System.out.println(a ^ b ^ b);//10
System.out.println(a ^ b ^ a);//20
10.一道面试题:
请自己实现两个整数变量的交换(默认int类型.)
例如
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b);
方式1:使用第三方变量(开发中用的)
int c = a;
a = b;
b = c;
System.out.println("a:"+a+",b:"+b);
System.out.println("------------");
方式2:用位异或实现(面试用)
左边:a,b,a
右边:a ^ b
a = a ^ b;
b = a ^ b; //a ^ b ^ b = a
a = a ^ b; //a ^ b ^ a = b
System.out.println("a:"+a+",b:"+b);
方式3:用变量相加的做法
a = a + b; //a=30
b = a - b; //b=10
a = a - b; //a=20
System.out.println("a:"+a+",b:"+b);
方式4:一句话搞定
b = (a+b) - (a=b); //b=30-20=10,a=20
System.out.println("a:"+a+",b:"+b);
11.<<:左移 左边最高位丢弃,右边补齐0
>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1
>>>:无符号右移 无论最高位是0还是1,左边补齐0
//<< 把<<左边的数据乘以2的移动次幂
System.out.println(3 << 2); //3*2^2 = 3*4 = 12;
//>> 把>>左边的数据除以2的移动次幂
System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6
System.out.println(24 >>> 2);
System.out.println(-24 >> 2);
System.out.println(-24 >>> 2);
分析
计算出3的二进制:11
00000000 00000000 00000000 00000011
(00)000000 00000000 00000000 0000001100
>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
1111111111 11111111 11111111 111010(00) 补码
补码:1111111111 11111111 11111111 111010
反码:1111111111 11111111 11111111 111001
原码:1000000000 00000000 00000000 000110
结果:-6
>>>的移动:
计算出24的二进制:11000
原码:10000000 00000000 00000000 00011000
反码:11111111 11111111 11111111 11100111
补码:11111111 11111111 11111111 11101000
11111111 11111111 11111111 11101000
0011111111 11111111 11111111 111010(00)
结果:
update 2015年9月9日00:27:03
12.&&:结果和&是一样的,只不过有短路效果。左边是false,右边不执行。
||:结果和|是一样的,只不过有短路效果。左边是true,右边不执行。
update 2015年9月14日23:13:32
Day 4
1.switch:表示这是switch选择结构
表达式:这个地方的取值是有限定的
byte,short,int,char
JDK5以后可以是枚举
JDK7以后可以是字符串
面试题
byte可以作为switch的表达式吗?
long可以作为switch的表达式吗?
String可以作为switch的表达式吗?
答:byte可以,long不可以,String在jdk7后可以
2.switch要注意break问题
例如
int a = 2;
int b = 3;
switch(a)
{
default:
b++;
case 3:
b++;
case 4:
b++;
}
switch语句只在遇到break才能停止,否则会一直执行下去
3.if语句和switch语句的区别?
if语句:
A:针对结果是boolean类型的判断
B:针对一个范围的判断
C:针对几个常量值的判断
switch语句:
针对几个常量值的判断
4.break
break:中断的意思
使用场景:
A:switch语句中
B:循环语句中。
(循环语句中加入了if判断的情况)
注意:离开上面的两个场景,无意义。
如何使用呢?
A:跳出单层循环
B:跳出多层循环
要想实现这个效果,就必须知道一个东西。带标签的语句。
格式:
标签名: 语句
带标签的break语句相当于goto语句
例子:
//跳出单层循环
for(int x=0; x<10; x++) {
if(x == 3) {
break;
}
System.out.println("HelloWorld");
}
//跳出多层循环
wc:for(int x=0; x<3; x++) {
nc:for(int y=0; y<4; y++) {
if(y == 2) {
//break nc;
break wc;
}
System.out.print("*");
}
System.out.println();
}
break wc;语句跳出两个for循环,而普通的break语句只能跳出内层单循环。
5.return:返回
A:用于结束方法的;
B:一旦遇到return,程序就不会在继续往后执行。
day5
1.方法
方法就是完成特定功能的代码块
在很多语言里面都有函数的定义
函数在Java中被称为方法
参数:
实际参数:就是实际参与运算的。
形式参数;就是方法定义上的,用于接收实际参数的。
2.方法调用
例子
public static void main(String[] args) {
int x = 10;
int y = 20;
//方式1:单独调用
//sum(x,y);
//方式2:输出调用
//System.out.println(sum(x,y));
//System.out.println(30);
//方式3:赋值调用
int result = sum(x,y);
//result在这里可以进行操作
System.out.println(result);
}
public static int sum(int a,int b) {
return a + b;
}
3.方法重载
实例
<span style="font-size:18px;">/* 需求:求两个数的和 */ class FunctionDemo4 { public static void main(String[] args) { //jvm会根据不同的参数去调用不同的功能 System.out.println(sum(10,20)); System.out.println(sum(10,20,30)); System.out.println(sum(10,20,30,40)); System.out.println(sum(10.5f,20)); } //需求1:求两个数的和 public static int sum(int a, int b) { System.out.println("int"); return a + b; } //需求2:求三个数的和 public static int sum(int a, int b, int c) { return a + b + c; } //需求3:求四个数的和 public static int sum(int a, int b, int c, int d) { return a + b + c + d; } public static float sum(float a,float b) { System.out.println("float"); return a + b + c + d; } }</span>
方法重载:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载特点:
与返回值类型无关,只看方法名和参数列表
在调用时,虚拟机通过参数列表的不同来区分同名方法
简言之:在同一个类中,方法名相同,参数列表不同,与返回值类型无关。
参数列表不同:
A:参数个数不同
B:参数类型不同
4.数组
数组:存储同一种数据类型的多个元素的容器。
定义格式:
A:数据类型[] 数组名;
B:数据类型 数组名[];
举例:
A:int[] a; 定义一个int类型的数组a变量
B:int a[]; 定义一个int类型的a数组变量
推荐使用第一种格式
对数组进行初始化
a:动态初始化 只指定长度,由系统给出初始化值
b:静态初始化 给出初始化值,由系统决定长度
动态初始化的格式:
数据类型[] 数组名 = new 数据类型[数组长度];
举例:
int[] arr = new int[3];
如何获取数组中的元素呢?
通过:
数组名[索引]
索引其实就是每个元素的编号,从0开始,最大索引是数组的长度-1。
例子
int[] arr = new int[3];
//用数组名和编号的配合就可以获取数组中的指定编号的元素。这个编号的专业叫法:索引
//通过数组名访问数据的格式是:数组名[索引];
System.out.println(arr); //[I@175078b 地址值。
System.out.println(arr[0]);//0
System.out.println(arr[1]);//0
System.out.println(arr[2]);//0
数组的静态初始化:
格式:数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
简化格式:
数据类型[] 数组名 = {元素1,元素2,…};
举例:
int[] arr = new int[]{1,2,3};
简化后:
int[] arr = {1,2,3};
注意事项:
不要同时动态和静态进行。
如下格式:
int[] arr = new int[3]{1,2,3}; //错误
5.数组操作的两个常见小问题:
ArrayIndexOutOfBoundsException:数组索引越界异常
原因:你访问了不存在的索引。
例如
int[] arr = {1,2,3};
System.out.println(arr[3]);
NullPointerException:空指针异常
原因:数组已经不在指向堆内存了。而你还用数组名去访问元素。
例如
//引用类型的常量:空常量 null
arr = null;
System.out.println(arr[0]);
6.数组逆序
例子
逆序
方式1:
public static void reverse(int[] arr) { for(int x=0; x<arr.length/2; x++) { int temp = arr[x]; arr[x] = arr[arr.length-1-x]; arr[arr.length-1-x] = temp; } }
方式2:
public static void reverse(int[] arr) { for(int start=0,end=arr.length-1; start<=end; start++,end--) { int temp = arr[start]; arr[start] = arr[end]; arr[end] = temp;
7.查找元素对应的索引值
基本查找
方式1:
public static int getIndex(int[] arr,int value) { for(int x=0; x<arr.length; x++) { if(arr[x] == value) { return x; } } return -1; }
方式2(特别注意!):
public static int getIndex(int[] arr,int value) { int index = -1; for(int x=0; x<arr.length; x++) { if(arr[x] == value) { index = x; break; } }
day06
1.二维数组
就是元素为一维数组的一个数组。
格式1
数据类型[][] 变量名 = new 数据类型[m]
;
m表示这个二维数组有多少个一维数组
n表示每一个一维数组的元素个数
举例:
int[][] arr = new int[3][2];
定义了一个二维数组arr
这个二维数组有3个一维数组,名称是arr[0],arr[1],arr[2]
每个一维数组有2个元素,可以通过arr[m]
来获取
表示获取第m+1个一维数组的第n+1个元素
注意:
A:以下格式也可以表示二维数组
a:数据类型 数组名[][] = new 数据类型[m]
;
b:数据类型[] 数组名[] = new 数据类型[m]
;
一个实例
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = new int[3][2];
//定义了一个二维数组arr
//这个二维数组有3个一维数组的元素
//每一个一维数组有2个元素
//输出二维数组名称
System.out.println(arr); //地址值 [[I@175078b
//输出二维数组的第一个元素一维数组的名称
System.out.println(arr[0]); //地址值 [I@42552c
System.out.println(arr[1]); //地址值 [I@e5bbd6
System.out.println(arr[2]); //地址值 [I@8ee016
//输出二维数组的元素
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
}
二维数组格式1的内存图解
格式2
数据类型[][] 数组名 = new 数据类型[m][];
m:表示这个二维数组有多少个一维数组。
列数没有给出,可以动态的给。这一次是一个变化的列数。
举例
public static void main(String[] args) {
//定义数组
int[][] arr = new int[3][];
System.out.println(arr); //[[I@175078b
System.out.println(arr[0]); //null
System.out.println(arr[1]); //null
System.out.println(arr[2]); //null
//动态的为每一个一维数组分配空间
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[1];
System.out.println(arr[0]); //[I@42552c
System.out.println(arr[1]); //[I@e5bbd6
System.out.println(arr[2]); //[I@8ee016
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
//ArrayIndexOutOfBoundsException
//System.out.println(arr[0][2]); //错误
arr[1][0] = 100;
arr[1][2] = 200;
}
格式1,格式2属于动态初始化
格式3
基本格式:
数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
简化版格式:
数据类型[][] 数组名 = {{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};
举例:
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
int[][] arr = {{1,2,3},{4,5},{6}};
举例
public static void main(String[] args) {
//定义数组
int[][] arr = {{1,2,3},{4,5},{6}};
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[0][0]); //1
System.out.println(arr[1][0]); //4
System.out.println(arr[2][0]); //6
System.out.println(arr[0][1]); //2
System.out.println(arr[1][1]); //5
//越界
System.out.println(arr[2][1]); //错误
}
2.二维数组的遍历
外循环控制的是二维数组的长度,其实就是一维数组的个数。
内循环控制的是一维数组的长度。
代码如下
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
//arr[0]就是第一个数组
//arr[0] = {1,2,3};
for(int x=0; x<arr[0].length; x++) {
System.out.println(arr[0][x]);
}
System.out.println("--------------");
for(int x=0; x<arr[1].length; x++) {
System.out.println(arr[1][x]);
}
System.out.println("--------------");
for(int x=0; x<arr[2].length; x++) {
System.out.println(arr[2][x]);
}
System.out.println("--------------");
//用循环改进
for(int x=0; x<3; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
System.out.println("--------------");
//3是我们根据上面的代码得出来的
//但是,它不能针对任何的数组都可以这样
//其实外面的这个循环的长度就是二维数组的长度
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
System.out.println("--------------");
//用方法改进
//调用方法
printArray2(arr);
System.out.println("--------------");
//我们再来一个列数是变化的
int[][] arr2 = {{1,2,3},{4,5},{6}};
printArray2(arr2);
}
/*
需求:遍历二维数组
两个明确:
返回值类型:void
参数列表:int[][] arr
*/
public static void printArray2(int[][] arr) {
for(int x=0; x<arr.length; x++) {
for(int y=0; y<arr[x].length; y++) {
System.out.print(arr[x][y]+" ");
}
System.out.println();
}
}
3.二维数组累加求和
核心代码
//通过遍历就可以得到每一个二维数组的元素。
for(int x=0; x<arr.length; x++)
{
for(int y=0; y<arr[x].length; y++)
{
//把元素累加即可。
sum += arr[x][y];
}
}
4.Java参数传递问题
Java中的参数传递问题:
基本类型:形式参数的改变对实际参数没有影响。
引用类型:形式参数的改变直接影响实际参数。
例子
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("a:"+a+",b:"+b); //a:10,b:20
change(a,b);
System.out.println("a:"+a+",b:"+b); //??? a:10,b:20
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println(arr[1]); //??? 4
}
public static void change(int a,int b) { //a=10,b=20
System.out.println("a:"+a+",b:"+b); //a:10,b:20
a = b; //a=20
b = a + b; //b=40
System.out.println("a:"+a+",b:"+b); //a:20,b:40
}
public static void change(int[] arr) { //arr={1,2,3,4,5};
for(int x=0; x<arr.length; x++) {
if(arr[x]%2==0) {
arr[x]*=2;
}
}
//arr={1,4,3,8,5};
}
一句话:在Java中,只有值传递,只不过基本类型传递的是基本类型的数据值,而引用类型传递的是地址值
6.面向对象思想
面向对象是基于面向过程的编程思想。
面向过程:强调的是每一个功能的步骤
面向对象:强调的是对象,然后由对象去调用功能
2:面向对象的思想特点
A:是一种更符合我们思想习惯的思想
B:可以将复杂的事情简单化
C:将我们从执行者变成了指挥者
举例:
买电脑:
面向过程:我的了解电脑--了解我自己的需求--找对应的参数信息--去中关村买电脑--讨价还价--买回电脑
面向对象:我知道我要买电脑 -- 班长去给我买 -- 班长就买回来了
洗衣服:
面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来
面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来
吃饭:
面向过程:去超市买菜--摘菜--洗菜--切菜--炒菜--盛起来--吃
面向对象:上饭店吃饭,你--服务员(点菜)--厨师(做菜)--服务员(端菜)--吃
3.开发,设计,特征
面向对象开发
就是不断的创建对象,使用对象,指挥对象做事情。
面向对象设计
其实就是在管理和维护对象之间的关系。
面向对象特征
封装(encapsulation)
继承(inheritance)
多态(polymorphism)
4.面向过程与面向对象
举例:把大象装进冰箱
面向过程:
动作有哪些呢?
A:打开冰箱门
B:装进大象
C:关闭冰箱门
面向对象:
我们怎么才能更符合面向对象思想呢?
A:有哪些类呢?
B:每个类有哪些东西呢?
C:类与类直接的关系是什么呢?
把大象装进冰箱的分析? (如何分析有哪些类呢?UML。名词提取法。)
A:有哪些类呢?
大象
冰箱
Demo
B:每个类有哪些东西呢?
大象:
进去
冰箱:
开门
关门
Demo:
main方法
C:类与类直接的关系是什么呢?
Demo中使用大象和冰箱类的功能。
5.现实世界中是如何描述一个事物的呢?
举例:学生
姓名,年龄,性别...
学习,吃饭,睡觉
属性:该事物的描述信息
行为:该事物能够做什么
我们学习编程语言,是为了模拟现实世界的事物的。
而我们学习的编程语言Java中最基本的单位是:类。
所以,我们就应该把事物通过类来体现出来:
由此,我们就得到了现实世界事物和类的对应关系:
事物: 类:
属性 成员变量
行为 成员方法
类:是一组相关的属性和行为的集合。是一个抽象的概念。
对象:是该类事物的具体表现形式。具体存在的个体。
举例:
学生:类
班长:对象
=================================
现实世界的事物
事物:
属性 人的身高,体重等
行为 人可以学习,吃饭等
Java中用class描述事物也是如此
类:
成员变量 就是事物的属性
成员方法 就是事物的行为
定义类其实就是定义类的成员(成员变量和成员方法)
===========================================================
6.
在一个java文件中写两个类:一个基本的类,一个测试类。
注意:文件名称和测试类名称一致。
如何使用呢?
创建对象使用。
如何创建对象呢?
格式:类名 对象名 = new 类名();
如何使用成员变量呢?
对象名.变量名
如何使用成员方法呢?
对象名.方法名(...)
7……
一个对象的内存图
二个对象的内存图
三个对象的内存图
使用类的内容
a:创建对象? 格式
类名 对象名 = new 类名();
b:如何使用成员变量和成员方法呢
对象名.成员变量
对象名.成员方法()
day07
1.成员变量和局部变量
一个实例
class Varialbe {
//成员变量
//int num = 10;
int num; //0
public void show() {
//int num2 = 20; //局部变量
//可能尚未初始化变量num2
//int num2; //没有默认值
int num2 = 20;
System.out.println(num2);
//int num = 100;
System.out.println(num);
}
}
class VariableDemo {
public static void main(String[] args) {
Varialbe v = new Varialbe();
System.out.println(v.num); //访问成员变量
v.show();
}
}
成员变量和局部变量的区别?
A:在类中的位置不同
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
B:在内存中的位置不同
成员变量:在堆内存
局部变量:在栈内存
C:生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同
成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
注意事项:
局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
例如,上面关于num的输出问题
2.
形式参数的问题:
基本类型:形式参数的改变不影响实际参数(值传递)
引用类型:形式参数的改变直接影响实际参数(引用传递)
===============================================================================
//形式参数是引用类型
class Student {
public void show() {
System.out.println("我爱学习");
}
}
class StudentDemo {
//如果你看到了一个方法的形式参数是一个类类型(引用类型),这里其实需要的是该类的对象。
public void method(Student s) {
//调用的时候,把main方法中的s的地址传递到了这里 Student s = new Student();
s.show();
}
}
class ArgsTest {
public static void main(String[] args) {
//形式参数是引用类型的调用
//需求:我要调用StudentDemo类中的method()方法
StudentDemo sd = new StudentDemo();
//创建学生对象
Student s = new Student();
sd.method(s); //把s的地址给到了这里
}
}
===============================================================================
3.匿名对象
匿名对象:就是没有名字的对象。
匿名对象的应用场景:
A:调用方法,仅仅只调用一次的时候。
注意:调用多次的时候,不适合。
那么,这种匿名调用有什么好处吗?
有,匿名对象调用完毕就是垃圾。可以被垃圾回收器回收。
B:匿名对象可以作为实际参数传递
class Student {
public void show() {
System.out.println("我爱学习");
}
}
class StudentDemo {
public void method(Student s) {
s.show();
}
}
class NoNameDemo {
public static void main(String[] args) {
//带名字的调用
Student s = new Student();//虽然也在堆内存里,但是有s地址连接着new Student(),new Student()不会这么快消失(只要s还存在)
s.show();
s.show();//同一个对象被调用两次
System.out.println("--------------");
//匿名对象
//new Student();
//匿名对象调用方法
new Student().show();
new Student().show(); //这里其实是重新创建了一个新的对象。因为这是在堆内存的,调用完就消失了
System.out.println("--------------");
匿名对象可以作为实际参数传递
//匿名对象作为实际参数传递
StudentDemo sd = new StudentDemo();
//Student ss = new Student();
//sd.method(ss); //这里的s是一个实际参数
//匿名对象
sd.method(new Student());
//在来一个
new StudentDemo().method(new Student());
4.
private:私有的。可以修饰成员变量和成员方法。
注意:被private修饰的成员只能在本类中访问。
封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
例子
class Student {
String name;
private int age;
//写一个方法对数据进行校验
public void setAge(int a) {
if(a < 0 || age > 120) {
System.out.println("你给的年龄有问题");
}else {
age = a;
}
}
//show()方法,显示所有成员变量值
public void show() {
System.out.println("姓名:"+name);
System.out.println("年龄:"+age);
}
}
class StudentDemo {
public static void main(String[] args) {
//创建学生对象
Student s = new Student();
s.show();
System.out.println("--------------");
//给成员变量赋值
s.name = "林青霞";
//s.age = 27;
s.setAge(27);
s.show();
System.out.println("--------------");
//给age赋值
//s.age = -27; //这个数据是不合理的,加上private后age只能在Student类中使用而不能在StudentDemo中使用
//通过方法给值
s.setAge(-27);
s.show();
System.out.println("--------------");
}
}
5.封装和private的应用:
A:把成员变量用private修饰
B:提高对应的getXxx()和setXxx()方法
class Student
{
private String name;
private int age;
public String getName()
{
return name;
}
public void setName(String n)
{
name = n;
}
public int getAge()
{
return age;
}
public void setAge(int a)
{
age = a;
}
}
//测试类
class StudentTest {
public static void main(String[] args)
{
//创建学生对象
Student s = new Student();
//使用成员变量
//错误:被私有修饰了,外界不能直接访问了
//System.out.println(s.name+"---"+s.age);
System.out.println(s.getName()+"---"+s.getAge());
//给成员变量赋值
//s.name = "林青霞";
//s.age = 27;
//通过方法给赋值
s.setName("林青霞");
s.setAge(27);
System.out.println(s.getName()+"---"+s.getAge());
}
}
6.this关键字
this:是当前类的对象引用。简单的记,它就代表当前类的一个对象。
注意:谁调用这个方法,在该方法内部的this就代表谁。
this的场景:
解决局部变量隐藏成员变量
例子
===================================================================
class Student {
private String name;
public String getName() {
return name;
/*public void setName(String n)
{
name = n;//不用this关键字的以前用法,但是s的名字不够鲜明于是改为name
}*/
public void setName(String name) { //name = "林青霞";
//name = name; //变量的使用规则:就近原则
//这里是类名,目前还没有说过类似的用法,所以这个是有问题的
//这里的调用只能通过对象名
//这个对象如果存在,它应该代表的是Student的一个对象。
//那么,谁能够代表当前类的对象呢? java就提供了一个关键字 this
//Student.name = name;
this.name = name;
}
}
class StudentTest {
public static void main(String[] args) {
//创建学生对象
Student s = new Student();
//给成员变量赋值
s.setName("林青霞");
System.out.println(s.getName());
}
}
==================================================================================
this:哪个对象调用那个方法,this就代表那个对象
this关键字的内存图解.bmp
7.构造方法
构造方法:
给对象的数据进行初始化
格式:
A:方法名与类名相同
B:没有返回值类型,连void都没有
C:没有具体的返回值
例子
class Student {
public Student() {
System.out.println("这是构造方法");
}
}
class ConstructDemo {
public static void main(String[] args) {
//创建对象
Student s = new Student();
System.out.println(s); //Student@e5bbd6
}
}
构造方法的注意事项:
A:如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
例子:
class Student
{
}
class ConstructDemo2
{
public static void main(String[] args)
{
//创建对象
Student s = new Student();
}
}
图解反编译前
反编译后
通过反编译可知
主要是new Student()引发的构造方法Student(反编译中的图解)public 为默认所以上图不显示
B:如果我们给出了构造方法,系统将不再提供默认的无参构造方法。(构造方法也可以重载,即带不同参数--默认不带参数)
注意:这个时候,如果我们还想使用无参构造方法,就必须自己给出。建议永远自己给出无参构造方法
8.
类的组成:成员变量,成员方法
今天我们又加入了一个新的成员:构造方法。
以后再提类的组成:
成员变量
构造方法
成员方法
图解
9.注意:
import必须出现在所有的class前面。
例如
1 import java.util.Scanner; 2 class …… 3 { 4 5 } 6 class …… 7 { 8 9 }
10.static
static的特点:(它可以修饰成员变量,还可以修饰成员方法)
A:随着类的加载而加载
回想main方法。
B:优先于对象存在
C:被类的所有对象共享
举例:咱们班级的学生应该共用同一个班级编号。
其实这个特点也是在告诉我们什么时候使用静态?
如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。
举例:
饮水机(用静态修饰)(饮水机可以多人共享使用)
水杯(不能用静态修饰)(水杯只能自己一个人用,原则上不可以共享,每个人都有一个)
D:可以通过类名调用
其实它本身也可以通过对象名调用。
推荐使用类名调用。
静态修饰的内容一般我们称其为:与类相关的,类成员
静态变量也可以通过类名调用.png
class Student {
//非静态变量
int num = 10;
//静态变量
static int num2 = 20;
}
class StudentDemo {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.num);
System.out.println(Student.num2);
System.out.println(s.num2);
}
}
static的内存图解
11.static关键字注意事项
A:在静态方法中是没有this关键字的
如何理解呢?
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
B:静态方法只能访问静态的成员变量和静态的成员方法
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
简单记:
静态只能访问静态。(非静态可以访问一切)
例子
1 class Teacher { 2 public int num = 10; 3 public static int num2 = 20; 4 5 public void show() { 6 System.out.println(num); //语句1,隐含的告诉你访问的是成员变量 7 System.out.println(this.num); //语句2,明确的告诉你访问的是成员变量,与语句1相同效果 8 System.out.println(num2); 9 10 //function(); 11 //function2(); 12 } 13 14 public static void method() { 15 //无法从静态上下文中引用非静态 变量 num 16 //System.out.println(num); 17 System.out.println(num2); 18 19 //无法从静态上下文中引用非静态 方法 function() 20 //function(); 21 function2(); 22 } 23 24 public void function() { 25 26 } 27 28 public static void function2() { 29 30 } 31 } 32 33 class TeacherDemo { 34 public static void main(String[] args) { 35 //创建对象 36 Teacher t = new Teacher(); 37 t.show(); 38 System.out.println("------------"); 39 t.method(); 40 } 41 }
12.静态变量和成员变量的区别
所属不同
静态变量属于类,所以也称为为类变量
成员变量属于对象,所以也称为实例变量(对象变量)
内存中位置不同
静态变量存储于方法区的静态区
成员变量存储于堆内存
内存出现时间不同
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
调用不同
静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用
13.
main方法的格式讲解:
public static void main(String[] args) {...}
public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。
static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。
void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。
main:是一个常见的方法入口。我见过的语言都是以main作为入口。
String[] args:这是一个字符串数组。值去哪里了?
这个东西到底有什么用啊?怎么给值啊?
这个东西早期是为了接收键盘录入的数据的。
格式是:
java MainDemo hello world java
例子
1 class MainDemo { 2 public static void main(String[] args) { 3 //System.out.println(args); //[Ljava.lang.String;@175078b 4 //System.out.println(args.length); //0 5 //System.out.println(args[0]); //ArrayIndexOutOfBoundsException 6 7 //接收数据后 8 System.out.println(args); 9 System.out.println(args.length); 10 //System.out.println(args[0]); 11 for(int x=0; x<args.length; x++) { 12 System.out.println(args[x]); 13 } 14 } 15 }
补充:
private是封装的一种表现。
思考题:构造方法中可不可以有return语句呢?
可以。而是写成这个样子:return;
day08
1.首先要注意,在同一个文件夹下,类定义在两个文件中和定义在一个文件中其实一样的。
2.例子
===========================================================================
class ArrayTool {
//把构造方法私有,外界就不能在创建对象了
private ArrayTool(){}
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
}
=====================================================
class ArrayDemo {
public static void main(String[] args) {
//定义数组
int[] arr = {28,55,37,46,19};
//需求:遍历数组
/*
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
*/
//如果我有多个数组都要进行遍历,那么,代码的重复度就很高
//如何改进呢?用方法改进
//调用
//静态方法
//printArray(arr);
//非静态方法
//ArrayDemo ad = new ArrayDemo();
//ad.printArray(arr);
//测试类的作用:创建其他类的对象,调用其他类的功能。
//而我们现在的操作是跟数组相关的,所以,你应该把这些操作定义到数组操作类中
//定义一个数组的操作类
//有了数组操作类之后的调用
//ArrayTool at = new ArrayTool();
//at.printArray(arr);
//方法改进为静态后,就可以直接通过类名调用
ArrayTool.printArray(arr);
}
/*
public static void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
*/
//假设该方法不是静态的
/*
public void printArray(int[] arr) {
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]);
}else {
System.out.print(arr[x]+", ");
}
}
}
*/
}
=======================================================================
3.***文档注释,文档说明书
注意:如何***一个说明书呢?
A:写一个工具类
B:对这个类加入文档注释
怎么加呢?
加些什么东西呢?
C:用工具解析文档注释
javadoc工具
D:格式
javadoc -d 目录 -author -version ArrayTool.java
目录:就可以写一个文件夹的路径
***帮助文档出错:
找不到可以文档化的公共或受保护的类:告诉我们类的权限不够(解决办法:在class前面加public)
实例
=================================================================================
/**
* 这是针对数组进行操作的工具类
* @author 刘意
* @version V.10
*/
public class ArrayTool {
//把构造方法私有,外界就不能在创建对象了
/**
* 这是私有构造
*/
private ArrayTool(){}
/**
* 这是遍历数组的方法,遍历后的格式是:[元素1, 元素2, 元素3, ...]
* @param arr 这是要被遍历的数组
*/
public static void printArray(int[] arr) {
System.out.print("[");
for(int x=0; x<arr.length; x++) {
if(x == arr.length-1) {
System.out.println(arr[x]+"]");
}else {
System.out.print(arr[x]+", ");
}
}
}
/**
* 这是获取数组中最大值的方法
* @param arr 这是要获取最大值的数组
* @return 返回数组中的最大值
*/
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;
}
/**
* 获取指定元素在数组中第一次出现的索引,如果元素不存在,就返回-1
* @param arr 被查找的数组
* @param value 要查找的元素
* @return 返回元素在数组中的索引,如果不存在,返回-1
*/
public static int getIndex(int[] arr,int value) {
int index = -1;
for(int x=0; x<arr.length; x++) {
if(arr[x] == value) {
index = x;
break;
}
}
return index;
}
}
==========================================================================================
4.如何查看API帮助文档
1:打开帮助文档
2:点击显示,找到索引,看到输入框
3:知道你要找谁?以Scanner举例
4:在输入框里面输入Scanner,然后回车
5:看包
java.lang包下的类不需要导入,其他的全部需要导入。
要导入:
java.util.Scanner
6:再简单的看看类的解释和说明,别忘了看看该类的版本
7:看类的结构
成员变量 字段摘要
构造方法 构造方法摘要
成员方法 方法摘要
8:学习构造方法
A:有构造方法 就创建对象
B:没有构造方法 成员可能都是静态的
9:看成员方法
A:左边
是否静态:如果静态,可以通过类名调用
返回值类型:人家返回什么,你就用什么接收。
B:右边
看方法名:方法名称不要写错
参数列表:人家要什么,你就给什么;人家要几个,你就给几个
实例
Math
Math:类包含用于执行基本数学运算的方法
由于Math类在java.lang包下,所以不需要导包。
特点:
没有构造方法,因为它的成员全部是静态的。
掌握一个方法:
获取随机数
public static double random():返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。
===========================================
class MathDemo {
public static void main(String[] args) {
//获取一个随机数
//double d = Math.random();
//System.out.println(d);
//需求:我要获取一个1-100之间的随机数,肿么办?
for(int x=0; x<100; x++) {
int number = (int)(Math.random()*100)+1;
System.out.println(number);
}
}
}
========================
实例2 /* 猜数字小游戏(1-100) */ import java.util.Scanner; class GuessNumber { public static void main(String[] args) { //程序产生一个随机数 int number = (int)(Math.random()*100)+1; //给出多次猜的机会,猜中就结束 while(true) { //键盘录入数据 Scanner sc = new Scanner(System.in); System.out.println("请输入你要猜的数据(1-100):"); int guessNumber = sc.nextInt(); if(guessNumber>number) { System.out.println("你要猜的数据"+guessNumber+"大了"); } else if(guessNumber<number) { System.out.println("你要猜的数据"+guessNumber+"小了"); } else { System.out.println("恭喜你,猜中了"); } } } }
5.代码块
局部代码块:局部位置,用于限定变量的生命周期
实例
/* 2 代码块 3 */ 4 class Code 5 { 6 7 } 8 class CodeDemo 9 { 10 public static void main(String[] args) 11 { 12 //局部代码块 13 { 14 int x = 10;//只在大括号内使用 15 System.out.println(x); 16 } 17 18 System.out.println(x);//报错,找不到符号 19 } 20 }
构造代码块:在类中的成员位置,用{}括起来的代码
特点:每次调用构造方法执行前,都会先执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起。
class Code
{
//构造代码块
{
//注意这一段外面不加大括号会报错,加大括号后就不报错
int x = 100;
System.out.println(x);
}
public Code()
{
System.out.println("code");//这个打印语句在第三个也就是最后一个才输出
}
{
int y = 200;
System.out.println(y);
}
}
class CodeDemo
{
public static void main(String[] args)
{
Code c = new Code();//每一次调用构造方法,都会先执行构造代码块,然后才执行构造方法里面的内容
}
}
静态代码块:在类中的成员位置用{}括起来的代码。只不过它用static修饰了
作用:一般是对类进行初始化(随着类的加载而加载)
class Code
{
//静态代码块
static
{
int a = 1000;
System.out.println(a);
}
//构造代码块
{
int x = 10;
System.out.println(x);
}
//静态代码块
static
{
int b = 2000;
System.out.println(b);//执行顺序是:先打印a(1000),再打印b(2000),最后才打印x(10)
}
}
由上图可以知道,1000只打印了一次,说明静态代码块只执行一次。
面试题:
静态代码块,构造代码块,构造方法的执行顺序?
静态代码块 --- 构造代码块 --- 构造方法
而且:静态代码块:只执行一次
构造代码块:每次调用构造方法都执行
由上图可知静态代码块只执行一次,第二次new Student()的时候不打印静态代码块
6.继承 extend
好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类之间产生了关系,是多态的前提
类与类产生了关系,其实也是继承的一个弊端:
类的耦合性增强了。
开发的原则:低耦合,高内聚。
耦合:类与类的关系
内聚:就是自己完成某件事情的能力
注意:Java不支持多继承,但支持多层继承
Java中继承的特点:
A:Java只支持单继承,不支持多继承。
有些语言是支持多继承,格式:extends 类1,类2,...
B:Java支持多层继承(继承体系)
class Father {}
class Mother {}
class Son exnteds Father {} //正确的
class Son extends Father,Mother {} // 错误的
Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
并且子类可以直接使用父类的父类的方法
例子
class GrandFather {
public void show() {
System.out.println("我是爷爷");
}
}
class Father extends GrandFather {
public void method(){
System.out.println("我是老子");
}
}
class Son extends Father {}
class ExtendsDemo2 {
public static void main(String[] args) {
Son s = new Son();
s.method(); //使用父亲的
s.show(); //使用爷爷的
}
}
7.继承的注意事项:
A:子类只能继承父类所有非私有的成员(成员方法和成员变量)(也就是说,父类带private的方法,变量都不可以访问)
B:子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
C:不要为了部分功能而去继承
什么时候考虑使用继承呢?
继承其实体现的是一种关系:"is a"。
Person
Student
Teacher
水果
苹果
香蕉
橘子
采用假设法。
如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。
8.类的组成:
成员变量:
构造方法:
成员方法:
类的组成部分的各自关系。
继承中成员变量的关系:
A:子类中的成员变量和父类中的成员变量名称不一样
B:子类中的成员变量和父类中的成员变量名称一样
在子类方法中访问一个变量的查找顺序:
a:在子类方法的局部范围找,有就使用
b:在子类的成员范围找,有就使用
c:在父类的成员范围找,有就使用
d:如果还找不到,就报错。
示例程序
1 class Father 2 { 3 public int num = 10; 4 } 5 class Son extends Father 6 { 7 public int num = 20; 8 9 public void show() 10 { 11 int num = 30;//就近原则 12 System.out.println(num); 13 } 14 } 15 16 class ExtendsDemo5 17 { 18 public static void main(String[] args) 19 { 20 Son s = new Son(); 21 s.show(); 22 } 23 }
好了,问题来了,我不仅仅要输出局部范围的num,还要输出本类成员范围的num。怎么办呢?(用this)
办法(修改于上一个程序)
public void show() {
int num = 30;
System.out.println(num);//就近原则num=30
System.out.println(this.num);//本类中的num=20
}
如果还想要输出父类成员范围的num。怎么办呢
super关键字
public void show() {
int num = 30;
System.out.println(num);//30
System.out.println(super.num);//父类num=10
}
总结
public void show() {
int num = 30;
System.out.println(num);//局部num
System.out.println(this.num);//本类num
System.out.println(super.num);//父类num
}
9.this和super的区别
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用,可以操作父类的成员)
怎么用呢?
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
10.继承中构造方法的关系
A:子类中所有的构造方法默认都会访问父类中空参数的构造方法
B:为什么呢?
因为子类会继承父类中的数据,可能还会使用父类的数据。
所以,子类初始化之前,一定要先完成父类数据的初始化。
注意:子类每一个构造方法的第一条语句默认都是:super();
如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
报错。
如何解决呢?
A:在父类中加一个无参构造方法
B:通过使用super关键字去显示的调用父类的带参构造方法
C:子类通过this去调用本类的其他构造方法
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意事项:
this(...)或者super(...)必须出现在第一条语句上。
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。
(第一条语句给不给它都默认有一个空的super语句,最好手动说明以免引起冲突)
11.一个类的初始化过程
成员变量进行初始化
默认初始化
显示初始化
构造方法初始化
看程序写结果
A:一个类的静态代码块,构造代码块,构造方法的执行流程
静态代码块 > 构造代码块 > 构造方法
B:静态的内容是随着类的加载而加载
静态代码块的内容会优先执行
C:子类初始化之前先会进行父类的初始化
运行结果是:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
*/
1 class Fu { 2 static { 3 System.out.println("静态代码块Fu"); 4 } 5 6 { 7 System.out.println("构造代码块Fu"); 8 } 9 10 public Fu() { 11 System.out.println("构造方法Fu"); 12 } 13 } 14 15 class Zi extends Fu { 16 static { 17 System.out.println("静态代码块Zi"); 18 } 19 20 { 21 System.out.println("构造代码块Zi"); 22 } 23 24 public Zi() { 25 System.out.println("构造方法Zi"); 26 } 27 } 28 29 class ExtendsTest2 { 30 public static void main(String[] args) { 31 Zi z = new Zi(); 32 } 33 }
12. A:成员变量的问题
int x = 10; //成员变量是基本类型
Student s = new Student(); //成员变量是引用类型
B:一个类的初始化过程
成员变量的初始化
默认初始化
显示初始化
构造方法初始化
C:子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化。
结果:
YXYZ
问题:
虽然子类中构造方法默认有一个super()
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。
例子
1 class X { 2 Y b = new Y(); 3 X() { 4 System.out.print("X"); 5 } 6 } 7 8 class Y { 9 Y() { 10 System.out.print("Y"); 11 } 12 } 13 14 public class Z extends X { 15 Y y = new Y(); 16 Z() { 17 //super (注意这里不要加super()) 18 System.out.print("Z"); 19 } 20 public static void main(String[] args) { 21 new Z(); 22 } 23 } 24 25 13.子类方法覆盖父类方法 26 class Father 27 { 28 public void show() 29 { 30 System.out.println("show Father"); 31 } 32 } 33 34 class Son extends Father 35 { 36 public void method() 37 { 38 System.out.println("method Son"); 39 } 40 41 public void show() 42 { 43 System.out.println("show Son"); 44 } 45 } 46 class ExtendsDemo8 47 { 48 public static void main(String[] args) 49 { 50 //创建对象 51 Son s = new Son(); 52 s.method(); 53 s.show(); 54 } 55 }
13.方法重写:子类中出现了和父类中方法声明一模一样的方法。
方法重载:
本类中出现的方法名一样,参数列表不同的方法。与返回值无
子类对象调用方法的时候:
先找子类本身,再找父类。
方法重写的应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。
例子
A:定义一个手机类。
B:通过研究,我发明了一个新手机,这个手机的作用是在打完电话后,可以听天气预报。
class Phone {
public void call(String name) {
System.out.println("给"+name+"打电话");
}
}
class NewPhone extends Phone {
public void call(String name) {
//System.out.println("给"+name+"打电话");
super.call(name); //避免重复代码
System.out.println("可以听天气预报了");
}
}
class ExtendsDemo9 {
public static void main(String[] args) {
NewPhone np = new NewPhone();
np.call("林青霞");
}
}
14.方法重写的注意事项
A:父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
B:子类重写父类方法时,访问权限不能更低(public 高)
最好就一致
C:父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中讲解
子类重写父类方法的时候,最好声明一模一样。
15.两个面试题
1:方法重写和方法重载的区别?方法重载能改变返回值类型吗?
方法重写:
在子类中,出现和父类中一模一样的方法声明的现象。
方法重载:
同一个类中,出现的方法名相同,参数列表不同的现象。
方法重载能改变返回值类型,因为它和返回值类型无关。
Override:方法重写
Overload:方法重载
2:this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this:代表当前类的对象引用
super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)
场景:
成员变量:
this.成员变量
super.成员变量
构造方法:
this(...)
super(...)
成员方法:
this.成员方法
super.成员方法
16.super
实例
//定义人类
class Person {
//姓名
private String name;
//年龄
private int age;
public Person() {
}
public Person(String name,int age) { //"林青霞",27
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//定义学生类
class Student extends Person {
public Student() {}
public Student(String name,int age) { //"林青霞",27
//this.name = name;
//this.age = age;
super(name,age);
}
}
class ExtendsTest4 {
public static void main(String[] args) {
//创建学生对象并测试
//方式1
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(27);
System.out.println(s1.getName()+"---"+s1.getAge());
//方式2
Student s2 = new Student("林青霞",27);
System.out.println(s2.getName()+"---"+s2.getAge());
}
补充笔记
API(Application Programming Interface)
应用程序编程接口(帮助文档)
day09
1.final引入
继承的代码体现
由于继承中方法有一个现象:方法重写。
所以,父类的功能,就会被子类给覆盖调。
有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
这个时候,针对这种情况,Java就提供了一个关键字:final
final:最终的意思。常见的是它可以修饰类,方法,变量。
2.final
final可以修饰类,方法,变量
特点:
final可以修饰类,该类不能被继承。
final可以修饰方法,该方法不能被重写。(覆盖,复写)
final可以修饰变量,该变量不能被重新赋值。因为这个变量其实常量。
常量:
A:字面值常量
"hello",10,true
B:自定义常量
final int x = 10;
3.final面试题
4.final修饰变量的初始化时机
A:被final修饰的变量只能赋值一次。
B:在构造方法完毕前。(非静态的常量)
5.多态
多态概述
某一个事物,在不同时刻表现出来的不同状态。
通过猫这个小动物,说猫可以被称为猫,也可以被称为动物。在不同时刻,猫表现出的不同状态,来说明多态.
举例:
猫可以是猫的类型。猫 m = new 猫();
同时猫也是动物的一种,也可以把猫称为动物。
动物 d = new 猫();
多态:同一个对象(事物),在不同时刻体现出来的不同状态。
举例:
猫是猫,猫是动物。
水(液体,固体,气态)。
多态的前提:
A:要有继承关系。
B:要有方法重写。
有父类引用指向子类对象
5. 多态中的成员访问特点:
A:成员变量
编译看左边,运行看左边。(意思是编译和运行都是看父类的,都是访问父类的成员,而变量不存在重写,父类的变量不会被子类覆盖)
B:构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
C:成员方法
编译看左边,运行看右边。(方法存在覆盖,存在方法重写,父类的方法被子类覆盖)
D:静态方法
编译看左边,运行看左边。(父类的静态方法不会被子类的静态方法所覆盖)
(静态和类相关,算不上重写,所以,访问还是左边的)
由于成员方法存在方法重写,所以它运行看右边。
完整代码
class Fu {
public int num = 100;
public void show() {
System.out.println("show Fu");
}
public static void function() {
System.out.println("function Fu");
}
}
class Zi extends Fu {
public int num = 1000;
public int num2 = 200;
public void show() {
System.out.println("show Zi");
}
public void method() {
System.out.println("method zi");
}
public static void function() {
System.out.println("function Zi");
}
}
class DuoTaiDemo {
public static void main(String[] args) {
//要有父类引用指向子类对象。
//父 f = new 子();
Fu f = new Zi();
System.out.println(f.num);
//找不到符号
//System.out.println(f.num2);
f.show();
//找不到符号
//f.method();
f.function();
}
}
6.
多态的好处:
A:提高了代码的维护性(继承保证)
B:提高了代码的扩展性(由多态保证)
例子(来源网上)
比如有一个父类superClass,它有2个子类subClass1,subClass2。superClass有一个方法 func(),两个子类都重写了这个方法。那么我们可以定义一个superClass的引用obj,让它指向一个子类的对象,比如superClass obj = new subClass1();那么我们调用obj.func()方法时候,会进行动态绑定,也就是obj它的实际类型的func()方法,即subClass1的func()方法。同样你写superClass obj = new subClass2();obj.func()其实调用的是subClass2的func()方法。这种由于子类重写父类方法,然后用父类引用指向子类对象,调用方法时候会进行动态绑定,这就是多态。多态对程序的扩展具有非常大的作用,比如你要再有一个subClass3,你需要改动的东西会少很多,要是使用了配置文件那就可以不动源代码了。
7.多态的弊端:
不能使用子类的特有功能。(因为编译左边)
Fu f = new Zi();//f不能调用Fu中没有而Zi特有的功能
想使用子类的特有功能?行不行?
行。
怎么用呢?
A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)
对象间的转型问题:
向上转型:
Fu f = new Zi();
向下转型:
Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。
实例
class Fu {
public void show() {
System.out.println("show fu");
}
}
class Zi extends Fu {
public void show() {
System.out.println("show zi");
}
public void method() {
System.out.println("method zi");
}
}
class DuoTaiDemo4 {
public static void main(String[] args) {
//测试
Fu f = new Zi();
f.show();
//f.method();
//创建子类对象,太占内存
//Zi z = new Zi();
//z.show();
//z.method();
//你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?
//如果可以,但是如下
Zi z = (Zi)f;//强制类型转换
z.show();
z.method();
}
}
多态继承中的内存图解
多态中的对象变化内存图解
ClassCastException:类型转换异常
一般在多态的向下转型中容易出现
8.多态案例
/* 2 不同地方饮食文化不同的案例 3 */ 4 class Person { 5 public void eat() { 6 System.out.println("吃饭"); 7 } 8 } 9 10 class SouthPerson extends Person { 11 public void eat() { 12 System.out.println("炒菜,吃米饭"); 13 } 14 15 public void jingShang() { 16 System.out.println("经商"); 17 } 18 } 19 20 class NorthPerson extends Person { 21 public void eat() { 22 System.out.println("炖菜,吃馒头"); 23 } 24 25 public void yanJiu() { 26 System.out.println("研究"); 27 } 28 } 29 30 class DuoTaiTest2 { 31 public static void main(String[] args) { 32 //测试 33 //南方人 34 Person p = new SouthPerson(); 35 p.eat(); 36 System.out.println("-------------"); 37 //转换成南方人 38 SouthPerson sp = (SouthPerson)p; 39 sp.eat(); 40 sp.jingShang(); 41 System.out.println("-------------"); 42 43 //北方人 44 p = new NorthPerson(); 45 p.eat(); 46 System.out.println("-------------"); 47 //转换成北方人 48 NorthPerson np = (NorthPerson)p; 49 np.eat(); 50 np.yanJiu(); 51 } 52 } 53
9.抽象类的概述:
动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。
我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。
抽象类的特点:
A:抽象类和抽象方法必须用abstract关键字修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类
C:抽象类不能实例化
因为它不是具体的。
抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?
用于子类访问父类数据的初始化
D:抽象的子类
a:如果不想重写抽象方法,该子类是一个抽象类。
b:重写所有的抽象方法,这个时候子类是一个具体的类。
抽象类的实例化其实是靠具体的子类实现的。是多态的方式。
Animal a = new Cat();
实例
//abstract class Animal //抽象类的声明格式
abstract class Animal {
//抽象方法
//public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体
public abstract void eat();
public Animal(){} //构造器
}
//子类是抽象类
abstract class Dog extends Animal {}
//子类是具体类,重写抽象方法
class Cat extends Animal {
public void eat() {
System.out.println("猫吃鱼");
}
}
class AbstractDemo {
public static void main(String[] args) {
//创建对象
//Animal是抽象的; 无法实例化
//Animal a = new Animal();
//通过多态的方式
Animal a = new Cat();
a.eat();
}
}
10. 抽象类的成员特点:
成员变量:既可以是变量,也可以是常量。
构造方法:有。
用于子类访问父类数据的初始化。
成员方法:既可以是抽象的,也可以是非抽象的。
抽象类的成员方法特性:
A:抽象方法 强制要求子类做的事情。
B:非抽象方法 子类继承的事情,提高代码复用性。
例子
abstract class Animal { 2 public int num = 10;//变量 3 public final int num2 = 20;//常量 4 5 public Animal() {}//无参构造方法 6 7 public Animal(String name,int age){}//带参构造方法 8 9 public abstract void show();//抽象方法 10 11 public void method() {//非抽象方法 12 System.out.println("method"); 13 } 14 } 15 16 class Dog extends Animal { 17 public void show() { 18 System.out.println("show Dog"); 19 } 20 } 21 22 class AbstractDemo2 { 23 public static void main(String[] args) { 24 //创建对象 25 Animal a = new Dog(); 26 a.num = 100; 27 System.out.println(a.num); 28 //a.num2 = 200; 29 System.out.println(a.num2); 30 System.out.println("--------------"); 31 a.show(); 32 a.method(); 33 } 34 }
11.体现多态的例子
abstract class Teacher {
//姓名
private String name;
//年龄
private int age;
public Teacher() {}
public Teacher(String name,int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象方法
public abstract void teach();
}
//基础班老师类
class BasicTeacher extends Teacher {
public BasicTeacher(){}
public BasicTeacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("基础班老师讲解JavaSE");
}
}
//就业班老师类
class WorkTeacher extends Teacher {
public WorkTeacher(){}
public WorkTeacher(String name,int age) {
super(name,age);
}
public void teach() {
System.out.println("就业班老师讲解JavaEE");
}
}
class AbstractTest2 {
public static void main(String[] args) {
//具体的类测试,自己玩
//测试(多态)
//基础班老师
Teacher t = new BasicTeacher();
t.setName("刘意");
t.setAge(30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
t = new BasicTeacher("刘意",30);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
//就业班老师
t = new WorkTeacher();
t.setName("林青霞");
t.setAge(27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
System.out.println("--------------");
t = new WorkTeacher("林青霞",27);
System.out.println(t.getName()+"---"+t.getAge());
t.teach();
}
}
上述程序的t被多次使用作很多用途,体现了一个t 的多态
12.多态小问题
一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
A:可以。
B:不让创建对象。
abstract不能和哪些关键字共存?
private 冲突(private要求不能重写,而abstract要求重写)
final 冲突
static 无意义
13.接口
接口的特点
接口的特点:
A:接口用关键字interface表示
interface 接口名 {}
B:类实现接口用implements表示
class 类名 implements 接口名 {}
C:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式来实例化。
D:接口的子类
a:可以是抽象类。但是意义不大。
b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用)
C:接口多态(最常用)
实例
//定义动物培训接口
interface AnimalTrain {
public abstract void jump();
}
//抽象类实现接口
abstract class Dog implements AnimalTrain {
}
//具体类实现接口
class Cat implements AnimalTrain {
public void jump() {
System.out.println("猫可以跳高了");
}
}
class InterfaceDemo {
public static void main(String[] args) {
//AnimalTrain是抽象的; 无法实例化
//AnimalTrain at = new AnimalTrain();
//at.jump();
AnimalTrain at = new Cat();
at.jump();
}
}
接口的变量默认是常量
接口的变量默认是静态的
14.接口成员特点
成员变量;只能是常量,并且是静态的。
默认修饰符:public static final
建议:自己手动给出。
构造方法:接口没有构造方法。
成员方法:只能是抽象方法。
默认修饰符:public abstract
建议:自己手动给出。
所有的类都默认继承自一个类:Object。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。
实例
interface Inter {
public int num = 10;
public final int num2 = 20;
public static final int num3 = 30;
//错误: 需要<标识符>
//public Inter() {}
//接口方法不能带有主体
//public void show() {}
//abstract void show(); //默认public
public void show(); //默认abstract
}
//接口名+Impl这种格式是接口的实现类格式
/*
class InterImpl implements Inter {
public InterImpl() {
super();
}
}
*/
class InterImpl extends Object implements Inter {
public InterImpl() {
super();
}
public void show() {}
}
//测试类
class InterfaceDemo2 {
public static void main(String[] args) {
//创建对象
Inter i = new InterImpl();
System.out.println(i.num);
System.out.println(i.num2);
//i.num = 100;
//i.num2 = 200;
//System.out.println(i.num); //无法为最终变量num分配值
//System.out.println(i.num2);//无法为最终变量num2分配值
System.out.println(Inter.num);
System.out.println(Inter.num2);
System.out.println("--------------");
}
}
15.类与类,类与接口,接口与接口的关系
类与类:
继承关系,只能单继承,可以多层继承。 层与层之间还是单继承。
类与接口:
实现关系,可以单实现,也可以多实现。
并且还可以在继承一个类的同时实现多个接口。
接口与接口:
继承关系,可以单继承,也可以多继承。(也就是说,java的类只能单继承,但是java的接口可以多继承)
例子
interface Father {
public abstract void show();
}
interface Mother {
public abstract void show2();
}
interface Sister extends Father,Mother {
}
//class Son implements Father,Mother //多实现
class Son extends Object implements Father,Mother {
public void show() {
System.out.println("show son");
}
public void show2() {
System.out.println("show2 son");
}
}
class InterfaceDemo3 {
public static void main(String[] args) {
//创建对象
Father f = new Son();
f.show();
//f.show2(); //报错
Mother m = new Son();
//m.show(); //报错
m.show2();
}
}
16.抽象类和接口的区别:
A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承
C:设计理念区别
抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。(相当于USB插口,可以插上东西实现扩展功能)
补充笔记
多态的分类:
a:具体类多态
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
b:抽象类多态
abstract class Fu {}
class Zi extends Fu {}
Fu f = new Zi();
c:接口多态
interface Fu {}
class Zi implements Fu {}
Fu f = new Zi();
(2)抽象类的特点
A:抽象类和抽象方法必须用关键字abstract修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
C:抽象类不能实例化
D:抽象类的子类
a:是一个抽象类。
b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。
抽象类的几个小问题
A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
用于子类访问父类数据的初始化
B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
为了不让创建对象
day10
1.形式参数
基本类型(太简单,不是我今天要讲解的)
引用类型
类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
抽象类:需要的是该抽象的类子类对象
接口:需要的是该接口的实现类对象
抽象类形式参数举例
===============================
abstract class Person {
public abstract void study();
}
class PersonDemo {
public void method(Person p) {//p; p = new Student(); Person p = new Student(); //多态
p.study();
}
}
//定义一个具体的学生类
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest {
public static void main(String[] args) {
//目前是没有办法的使用的
//因为抽象类没有对应的具体类
//那么,我们就应该先定义一个具体类
//需求:我要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
}
}
===========================================================
接口形式参数举例//在这里跟抽象类有点相似
====================================
//定义一个爱好的接口
interface Love {
public abstract void love();
}
class LoveDemo {
public void method(Love l) { //l; l = new Teacher(); Love l = new Teacher(); 多态
l.love();
}
}
//定义具体类实现接口
class Teacher implements Love {
public void love() {
System.out.println("老师爱学生,爱Java,爱林青霞");
}
}
class TeacherTest {
public static void main(String[] args) {
//需求:我要测试LoveDemo类中的love()方法
LoveDemo ld = new LoveDemo();
Love l = new Teacher();
ld.method(l);
}
}
2.返回值类型
基本类型:(基本类型太简单,我不准备讲解)
引用类型:
类:返回的是该类的对象
抽象类:返回的是该抽象类的子类对象
接口:
返回类型是类举例
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
//Student s = new Student();
//Student ss = s;
//Student s = new Student();
//return s;
return new Student();
}
}
class StudentTest2 {
public static void main(String[] args) {
//需求:我要使用Student类中的study()方法
//但是,这一次我的要求是,不要直接创建Student的对象
//让你使用StudentDemo帮你创建对象
StudentDemo sd = new StudentDemo();
Student s = sd.getStudent(); //new Student(); Student s = new Student();
s.study();
}
}
返回类型是抽象类举例
abstract class Person {
public abstract void study();
}
class PersonDemo {
public Person getPerson() {
//Person p = new Student();
//return p;
return new Student();
}
}
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest2 {
public static void main(String[] args) {
//需求:我要测试Person类中的study()方法
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //new Student(); Person p = new Student(); 多态
p.study();
}
}
接口同理
3.链式编程
/*
链式编程。
每次调用完毕方法后,返回的是一个对象。
*/
class Student {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class StudentDemo {
public Student getStudent() {
return new Student();
}
}
class StudentTest3 {
public static void main(String[] args) {
//如何调用的呢?
StudentDemo sd = new StudentDemo();
//Student s = sd.getStudent();
//s.study();
//链式编程
sd.getStudent().study();
}
}
4.包
A:其实就是文件夹
B:作用
a:把相同的类名放到不同的包中
b:对类进行分类管理
举例
学生:增加,删除,修改,查询
老师:增加,删除,修改,查询
方案1:按照功能分
cn.itcast.add
AddStudent
AddTeacher
cn.itcast.delete
DeleteStudent
DeleteTeacher
cn.itcast.update
UpdateStudent
UpdateTeacher
cn.itcast.find
FindStudent
FindTeacher
方案2:按照模块分
cn.itcast.teacher
AddTeacher
DeleteTeacher
UpdateTeacher
FindTeacher
cn.itcast.student
AddStudent
DeleteStudent
UpdateStudent
FindStudent
包的定义
package 包名;
多级包用.分开即可
注意事项:
A:package语句必须是程序的第一条可执行的代码
B:package语句在一个java文件中只能有一个
C:如果没有package,默认表示无包名
5.带包的编译和运行:
A:手动式
a:编写一个带包的java文件。
b:通过javac命令编译该java文件。
c:手动创建包名。
d:把b步骤的class文件放到c步骤的最底层包
e:回到和包根目录在同一目录的地方,然后运行
带包运行。
B:自动式
a:编写一个带包的java文件。
b:javac编译的时候带上-d即可
javac -d . HelloWorld.java
(注意不要漏掉点号)
c:回到和包根目录在同一目录的地方,然后运行
带包运行。
6.导包:
格式:import 包名;
这种方式导入是到类的名称。
注意:我们用谁就导谁。(尽量少用星号*)
面试题:
package,import,class有没有顺序关系?
有。
package > import > class
Package:只能有一个
import:可以有多个
class:可以有多个,以后建议是一个
7.权限修饰符:
8.修饰符:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
除此以外的组合规则:
成员变量:public static final
成员方法:public static
public abstract
public final
9.内部类
内部类概述:
把类定义在其他类的内部,这个类就被称为内部类。
举例:在类A中定义了一个类B,类B就是内部类。
内部的访问特点:
A:内部类可以直接访问外部类的成员,包括私有。
B:外部类要访问内部类的成员,必须创建对象。
*/
class Outer {
private int num = 10;
class Inner {
public void show() {
System.out.println(num);
}
}
public void method() {
//找不到符号
//show();
Inner i = new Inner();
i.show();
}
}
class InnerClassDemo {
public static void main(String[] args) {
}
}
10.
内部类位置
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。
成员位置:在成员位置定义的类,被称为成员内部类。
class Outer {
private int num = 10;
//成员位置
/*
class Inner {
}
*/
public void method() {
//局部位置
class Inner {
}
}
}
class InnerClassDemo2 {
public static void main(String[] args) {
}
}
11.成员内部类:
如何直接访问内部类的成员。
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
例子
class Outer {
private int num = 10;
class Inner {
public void show() {
System.out.println(num);
}
}
}
class InnerClassDemo3 {
public static void main(String[] args) {
//需求:我要访问Inner类的show()方法
//Inner i = new Inner();
//i.show();
//格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
12.成员内部类的修饰符:
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰。
案例:我有一个人(人有身体,身体内有心脏。)
class Body {
private class Heart {
public void operator() {
System.out.println("心脏搭桥");
}
}
public void method() {
if(如果你是外科医生) {
Heart h = new Heart();
h.operator();
}
}
}
按照我们刚才的讲解,来使用一下
Body.Heart bh = new Body().new Heart();
bh.operator();
//加了private后,就不能被访问了,那么,怎么玩呢?
Body b = new Body();
b.method();
例子
===============================================
class Outer {
private int num = 10;
private static int num2 = 100;
//内部类用静态修饰是因为内部类可以看出是外部类的成员
public static class Inner {
public void show() {
//System.out.println(num);
System.out.println(num2);
}
public static void show2() {
//System.out.println(num);
System.out.println(num2);
}
}
}
class InnerClassDemo4 {
public static void main(String[] args) {
//使用内部类
// 限定的新静态类
//Outer.Inner oi = new Outer().new Inner();
//oi.show();
//oi.show2();
//成员内部类被静态修饰后的访问方式是:
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
oi.show();
oi.show2();
//show2()的另一种调用方式
Outer.Inner.show2();
}
}
===========================================================
13.面试题
注意:
1:内部类和外部类没有继承关系。
2:通过外部类名限定this对象
Outer.this
14.局部内部类
局部内部类
A:可以直接访问外部类的成员
B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
面试题:
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须用final修饰
B:为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。(个人理解,也就是说,不会立刻消失的method方法已经无法知道它的内部类的方法中的num2究竟是什么来的,毕竟num2已逝去)
而堆内存的内容并不会立即消失。所以,我们加final修饰。
加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
我在内存中存储的是数据20,所以,我还是有数据在使用。
(这个可以用xjad软件反编译理解)
例子
===============================
class Outer { 2 private int num = 10; 3 4 public void method() { 5 //int num2 = 20; 6 //final int num2 = 20; 7 class Inner { 8 public void show() { 9 System.out.println(num); 10 //从内部类中访问本地变量num2; 需要被声明为最终类型 11 System.out.println(num2);//20 12 } 13 } 14 15 //System.out.println(num2); 16 17 Inner i = new Inner(); 18 i.show(); 19 } 20 } 21 22 class InnerClassDemo5 { 23 public static void main(String[] args) { 24 Outer o = new Outer(); 25 o.method(); 26 } 27 }
=============================================================
15.匿名内部类
匿名内部类
就是内部类的简化写法。
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类。
格式:
new 类名或者接口名(){
重写方法;
}
本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象。(再次强调,是子类匿名对象,子类!)
当里面有两个方法时,如何调用?
完整代码
interface Inter { 2 public abstract void show(); 3 public abstract void show2(); 4 } 5 6 class Outer { 7 public void method() { 8 //一个方法的时候 9 /* 10 new Inter() { 11 public void show() { 12 System.out.println("show"); 13 } 14 }.show(); 15 */ 16 17 //二个方法的时候 18 /*注释中是一个一个调用 19 new Inter() { 20 public void show() { 21 System.out.println("show"); 22 } 23 24 public void show2() { 25 System.out.println("show2"); 26 } 27 }.show(); 28 29 new Inter() { 30 public void show() { 31 System.out.println("show"); 32 } 33 34 public void show2() { 35 System.out.println("show2"); 36 } 37 }.show2(); 38 */ 39 40 //如果我是很多个方法,就很麻烦了 41 //那么,我们有没有改进的方案呢? 42 Inter i = new Inter() { //多态 43 public void show() { 44 System.out.println("show"); 45 } 46 47 public void show2() { 48 System.out.println("show2"); 49 } 50 }; 51 52 i.show(); 53 i.show2(); 54 } 55 } 56 57 class InnerClassDemo6 { 58 public static void main(String[] args) { 59 Outer o = new Outer(); 60 o.method(); 61 } 62 } 63
代码解析
完整代码对比
interface Person {
public abstract void study();
}
class PersonDemo {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
public void method(Person p) {
p.study();
}
}
//实现类
class Student implements Person {
public void study() {
System.out.println("好好学习,天天向上");
}
}
class InnerClassTest2 {
public static void main(String[] args) {
//测试
PersonDemo pd = new PersonDemo();
Person p = new Student();
pd.method(p);
System.out.println("--------------------");
//匿名内部类在开发中的使用
//匿名内部类的本质是继承类或者实现了接口的子类匿名对象
pd.method(new Person(){
public void study() {
System.out.println("好好学习,天天向上");
}
});
}
}
16.匿名内部类面试题:
按照要求,补齐代码
interface Inter { void show(); }
class Outer { //补齐代码 }
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
========================================================
interface Inter {
void show();
//public abstract
}
class Outer {
//补齐代码
public static Inter method() {
//子类对象 -- 子类匿名对象
return new Inter() {
public void show() {
System.out.println("HelloWorld");
}
};
}
}
class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
/*
1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
2:Outer.method().show()可以看出method()方法的返回值是一个对象。
又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
*/
}
}
day10补充笔记
链式编程
对象.方法1().方法2().......方法n();
这种用法:其实在方法1()调用完毕后,应该一个对象;
方法2()调用完毕后,应该返回一个对象。
方法n()调用完毕后,可能是对象,也可以不是对象。
相关文章推荐
- Java 8十个lambda表达式案例
- Java Lambda表达式入门
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
- 从根本上改变我们开发Java程序的方式:Lambda
- Java 8:Lambda表达式试水
- Java 8为什么需要Lambda表达式
- Java日志方案概述
- 单点登录cas与权限管理框架shiro集成-spring项目方式
- springMVC(5) springMVC一个controller写多个方法
- CAS和Shiro在spring中集成
- Java面向切面编程(AOP模式)
- Java笔记——面向切面编程(AOP模式)
- java读取properties文件
- JDK 5 Annotation\注解\注释\自定义注解
- Springmvc中 同步/异步请求参数的传递以及数据的返回
- java初学习
- JVM性能优化,Java的伸缩性
- Java日志终极指南
- Myeclipse注册码
- Java 自定义实现 LRU 缓存算法