java基础复习篇
前言
-
笔者的java没有经过真正系统的学习过,在B站自学的。所以有些地方难免会理解错误之类的,如果看到错误的地方,请指出来,或者有什么不理解的地方也可以提出来,大家一起进步。
-
这篇教程是一个学习方向的引导,且只针对基础入门(更加进阶的知识笔者也还在学习)。
-
java的基础入门知识网上有很多,很多大神的博客里也有总结,笔者不认为自己能比大神总结的好。所以在这篇教程里,很多基础知识笔者会直接引用一些大神的博客和网上的一些资料,做一个汇总。当然,同时也会加入笔者自己的理解,说一些笔者学习时踩过的坑,分享一些心得。
第一章:java的环境搭建
Java开发工具和资源(超全版)
百度网盘链接:https://pan.baidu.com/s/10bKNbe0Jx6wF1jx9TMhqZA
提取码:krpc
配置环境变量
java中的注释
专业注释:可以用工具javadoc.class提取的注释
/**
- javadoc注释 被javadoc.exe提取解析生成help文档
- javadoc注释
- javadoc注释
*/
单行注释://
多行注释:
/*
多行注释
多行注释
多行注释
*/
编写HelloWorld
public class HolleWorld{
//类体:只允许编译变量
//入口
public static void main(String[] args){
//方法体
//java语句
System.out.println("hello world!");
}
}
public class和class的区别
一个文件可以有多个class
一个文件可以没有public class
有几个class就有几个.class文件
public class 命名只能有一个,且必须与源文件命名一致
每一个class都可以编写main方法,设定程序入口,执行main
第二章:java语言基础
标识符
1、什么是标识符?
程序员自己命名的单词
黑色字体高亮显示
可以标识
*类名
*方法名
*变量名
*接口名
*常量名
……
2、命名规则
必须由数字、字母、下划线、$组成
不能以数字开头
严格区分大小写
关键字不能做标识符
无长度限制
3、命名规范(不属于语法,方便自己他人读程序
*见名知意
*驼峰命名方式
SystemService
类名、接口名 : 每个单词首字母大写
变量名、方法名: 首字母小写,后每个单词、首字母大写
常量名 : 每个字母大写并用下划线隔开
关键字
在java中有特殊意义的单词
不能作为变量名、方法名、类名存在
在编译器中常被高亮提示
关键字中所有字母都为小写
字面值
即数据 源程序的组成部分
数据类型:
布尔型true/false
整数型
浮点型
字符串“”
字符型
变量
1、什么是变量?
*内存中的一块空间,有数据类型,名字,字面值
*是存储数据的基本单元
*字面值是变量的一部分
2、数据类型的作用?
*指导程序运行时分配内存空间大小
3、变量中存取的数据必须与数据类型一致
4、声明/定义变量语法格式:
变量类型 变量名;
int i;
5、声明后赋值:
变量名=字面值;
先运算=右边的表达式;
6、声明和赋值可以一起完成;
7、赋值之后可重新赋值;
8、变量使内存中的空间可以重复使用
9、没赋值之前没法访问
2、java中的变量
变量的作用域
1、什么是作用域?
变量的作用域,变量的有效范围
2、出大括号就不认识
3、静态变量可以在类内调用(static int k=100;)
4、变量的分类
根据变量声明的位置
*局部变量
方法体内
*成员变量
方法体外(类体内
同一作用域变量不能重名
数据类型
-
引用数据类型:
String
java.math.……
类
接口-
基本数据类型:
数据类型 单位字节=8 bit(位)默认值
整数型 byte 1,-128~127 256 0 short 2,-32768~32767 0 int 4,-2147483648~ 0 long 8 0L 浮点型 float 4, double 8 布尔型 boolean 1 字符型 char 2
整数型字面值默认当做int。在后面添加L/l可以被当做long处理
long a=2147483648;//出错
long a=2147483648L;//不出错
2)java整数型字面值
十进制 a=10; 八进制 b=010; 十六进制 c=0x10; print(a+b+c);*但最后输出是以十进制输出
3)类型转换
小容量可以转换成大容量(自动类型转)long i=123;
4)大容量转换成小容量要强制类型转换(加强制类型转换符
编译可以通过,但是精度可能会损失严重
*转换原理(补码
原始数据:00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
将左边多余字节删去4、字符串不属于基本数据类型(引用数据类型
*使用双引号“”5、字符编码
计算机最初只支持英文:ASCII
‘a‘//jdk中bin下 native2ascii.exe,将文字转换成unicode码
//命令行中输入native2ascii,输入中文
//ctrl+c退出 -
浮点型
float 单精度 4字节
double 双精度 8字节
财务软件要求更高精度
引用数据类型
java.math.BijDecimal
java的 SE类库字节码:D:\Program Files\Java\jdk1.8.0_221\jre\lib\rt
SE类库原码 :D:\Program Files\Java\jdk1.8.0_221\scr
所有浮点值字面值都默认为double
**double和float在计算机中存的是近似值
boolean
java中boolean只有两个值true false 无其他值
底层存储boolean类型占用1个字节,
在逻辑运算和条件控制语句中使用,判断
数据类型之间的相互转换:
1、除boolean剩下7种可以相互转换
2、小容量向大容量转换,自动转换
byte< short< char< int< long< float< double 数据类型 单位字节=8 bit(位)默认值
----------------------------------------------
整数型
byte 1,-128~127 256 0
short 2,-32768~32767 0
int 4,-2147483648~ 0
long 8 0L
浮点型
float 4,
double 8
布尔型
boolean 1
字符型
char 2
----------------------------------------------
*任何浮点型都比整数容量大
char和short可表示种类数量相同,但是char可以去更大啊正
整数
char c=97;
3、大容量转换成小容量可能损失精度
4、当整数字面值没有超出byte、short、char取值范围,可直
接赋值
5、byte、short、char混合运算,各自先转成int类型再做运算
6、多种数据类型混合运算,先转换成容量大的那种数据类型
再运算
//编译的时候不做运算,只检验语法
long g/3=10;
byte h=(byte)(int)g/3;//精度损失错误
byte h=(byte)(int)(g/3);//可以
运算符
算术运算符:
+
-
*
/
%
++
--
不确定运算符优先级可以加小括号提升优先级
关系运算符:
<
>
==结果是布尔类型boolean,结果是true或false
>=
<=
!=
逻辑运算符:
&与
|或
!非
^逻辑异或
&&短路与
||短路或
*逻辑运算要求两边算子都是布尔型,运算结果也是布尔型
*短路与和逻辑与最终运算结果一样,只不过存在短路现象
*第一个式子结果是true,执行短路或||
*第一个式子结果是false,执行短路与&&
关于java两种赋值类运算符
*基本赋值运算符
=
*扩展运算符
+=
-=
*=
/=
%=
*先执行=右边表达式再将结果赋值给左边
*byte b=10;//int long
i+=5;等同于i=(byte)(i+5);
*扩展类运算符不改变结果类型
关于java中“+”运算符:
*求和
*字符串连接运算
*+号两边都是数字才做加法运算,否则就是字符串
连接运算结果为字符串
*一个表达式中可以有多个+,自左向右运算
三目运算符
布尔表达式?表达式1:表达式2
true 选表达式1
false 选表达式2
从键盘上读入
关键语句
java.util.Scanner s = new java.util.Scanner(System.in);
public class KeyInput{
public static void main(String[] args){
java.util.Scanner s = new java.util.Scanner(System.in);
//调用Scanner对象的next()方法开始录入
//
//
//回车键输入
String userInputContent = s.next();//得到字符串
int num = s.nextInt();//得到数字
System.out.println(num+userInputContent);
}
}
控制语句
包括
*选择语句
-if,if……else
-switch
*循环结构
-for
-while
-do……while
*控制循环语句
-bresk
-comtinue
while语句
1、while(布尔表达式){
循环体
}
do{
}while(布尔表达式);
2、执行原理:
1)while布尔表达式
2)do……while循环体
布尔表达式
3、循环次数:
while do……while
----------------------
0~N次 1~N
可以为0次 至少一次
for语句
1、if语法结构:4
第一种
if(boolean式){
Java语句;
Java语句;
……
}
第二种
if(boolean式){
Java语句;
Java语句;
……
}
else{
Java语句;
Java语句;
……
}
第三种:
if(boolean式){
}
else if(boolean式){
}
else if(boolean式){
}
*一个if执行完成整个选择表达式结束
第四种
else{}
*带else的可100%保证会有分支执行
*所有条件控制语句可以合理嵌套使用
*使用大括号包围要缩进
for(初始表达式;布尔表达式;更新表达式);
循环
for循环执行原理:
1、只有两个;是必须的
2、初始表达式只在最初执行一次
3、布尔表达式只能是true/false
4、执行过程:
初始表达式
布尔表达式
为真:循环体
更新表达式
……
布尔表达式
为假:停止
寻找素数
public class ForTest{
public static void main(String[] args){
//寻找素数 : 1~N
java.util.Scanner s = new java.util.Scanner(System.in);
System.out.println("请输入一个正整数:");
int N = s.nextInt();
boolean isSuShu = true;//做标记,输出的时候判断N是否为素数
int count = 0;
for(int i=2;i<=N;i++){
for(int j=2;j<=i/2;j++){
if(i%j==0){
isSuShu = false;
break;
}
}
//每8个换一行
if(isSuShu){
System.out.print(i+"\t");
count++;
if(count == 8){
System.out.print("\n");
count = 0;
}
}
//System.out.println(isSuShu ? i+"是素数": i+"不是素数");
isSuShu = true;
}
/*
for(int i=2;i<=N/2;i++){
if(N%i==0){
isSuShu = false;//标记
break;
}
}
//灵活判断,输出即可
System.out.println(isSuShu ? i+\t"是素数": i+"不是素数");
*/
}
}
关于switch:
switch(int或string类型的字面值或变量){
case int或string类型的字面值或变量; //匹配
java语句;
java语句;
……
break;
case int或string类型的字面值或变量; //匹配
java语句;
java语句;
……
break;
……
default;//默认,相当于else
java语句;
……
}
*switch执行原理:
*switch后数据与case后数据一一匹配,成功的分支执行
*自上而下依次比较,分支最后有bresk语句,整个switch语句终止;
没有break的话直接进入下一个分支进行执行——case穿现象
*没有分支匹配成功,执行default
switch(int或string类型的字面值或变量)
case int或string类型的字面值或变量;
byte、short、char可以自动转换int
*jdk6 switch和case只能int
*case可以合并
case 1:case 2:case 10:
java语句;
方法
1、使用"方法"(函数!)
Method:
在C语言中叫函数:Function
方法定义在类体中,方法在类中可以有多个,没有先后之分
方法体中不能再定义方法。
方法体由java语句构成。自上而下依次执行。
方法格式:
[修饰符列表] 返回值类型 方法名 【形参表】{
方法体;
return 值;
}
2、解释:
修饰符列表:
*可选项,不是必需
*有static的其用 类名.方法名 调用
返回值类型:
*什么是返回值?
一个方法运行结束,结果可能是一个数据——其为返回值
*返回值类型
所有基本类型:
引用类型 :
*返回值类型不是void,方法结束必须返回一个具体的数值,不然会报错
【return 值;】
返回值类型是void,可以有return;若执行则所在方法结束!
3、方法名(合法标识符就行)
见名知意,最好是动词
驼峰命名法则
首字母小写,后每个单词首字母大写
4、形参表:
*形参是局部变量
*个数可以是0~N个
*形参用逗号隔开
3、方法调用
方法调用才会执行
语法调用:*有static的其用 类名.方法名 调用
顺序:
main调用方法:最后调用最先结束
最先调用最后结束
main最先调用,最后结束
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
。
1、方法只定义不调用,不会执行,不会分配内存空间
只有执行时才动态给这个方法分配内存空间
2、在jvm有三块主要空间:(还有其他空间
*方法内存
*堆内存
*栈内存
3、关于栈的数据结构
*栈 stack 是一种数据结构
*数据结构反映的是数据的存储形态
*数据结构是独立的学科,
*常见:
-数组
-队列
-栈
-链表
-二叉树
-哈希表
…………
4、方法代码片段在哪里?内存哪里分配?
*方法代码片段属于.class字节码文件的一部分,
字节码文件在类加载的时候
将其放到了方法区中,所以JVM的三块主要空间中方法区
最先有数据
存放代码片段
*代码可以重复调用,每一调用栈内存都要为其分
配活动场所,
5、方法在调用瞬间,会给该方法分配内存空间,会入栈操作
方法执行结束后,给该方法分配的空间全部释放
6、 局部变量在方法体中声明,局部变量运行阶段内存由
栈分配!
递归
1、方法第递归调用
2、递归调用很耗费栈内存,能不用不要用
3、递归不停止,栈内存溢出错误,JVM停止工作
4、递归必须有结束条件
5、递归即使有结束条件,也可能栈内存溢出
注意:
目录拷贝要用到!
public class RecursionTest{
Student sj;
public static void main(String[] args){
int i = 10;
//doSome(i);
System.out.println(method(5));
}
public static int method (int n){
if(n == 1)
return 1;
return n*method(n-1);
}
public static int sum (int n){
if(n == 1)
return 1;
return n+sum(n-1);
}
public static void doSome(int i){
System.out.println(i);
i--;
if(i>0)
doSome(i);
}
}
第三章:面向对象
(my)eclipse的一些使用技巧
*(my)eclipse的使用
workplace:
-打开时会有工作区提示,
-可以开启多个回话,建立多个工作区
*在workplace中有文件夹:.metadata
-在其中存储当前eclipse的工作状态
-删除它后再打开myeclipse后是全新的开始
*打开myeclipse后:
-窗口不小心关闭了,再次打开
window->show vive->other :要找的窗口
*myeclipse有很多布局方式
-企业及开发:javaEE开发专用布局:MyEclipse Java Enteprise
-普通java开发:javaSE:-java
-怎么切换:
myeclipse右上角
*这个布局被破坏了想要还原:
-window->Reset……
*窗口介绍
-Package Explore/Navigator/Project Explore:可看到java源文件
*Console:控制台窗口
*基本单元:Project
-使用myeclipse创建工程
-在Package Explore窗口右键–>new–>java project
*指定java工程名称:一般全小写
*指定java工程存放目录
*java运行环境:jre配置【可选myeclipse自带的jre,也可选自检转的】
*Project layout:工程的目录布局
-可自选,两个独立的文件夹存放原码(src)和字节码(bin)
在src目录下新建软件包:
-在src目录上右键–>new–>packsge
-给package起名:com.xxxxx.javase
-包package是语法的一部分
*在软件包下新建一个java类:
-在包上点击右键–>new–>class【勾上生成main方法】
-显示行号:在java源程序的左侧栏上右键:show line number
设置字体大小(字体段落颜色等等也在这里设置):
window->Preferences->输入font->colors and fonts->Basic->Text Font->Edit编辑字号大小
*常用快捷键
-ctrl+d删除一行
-alt+/自动补全
-ctrl+1纠错
-ctrl+alt+down
-ctrl+shift+f 格式化代码
*快捷键怎么设置
window->Preferences->keys
myeclipse不保存不会编译
*带红色波浪下划线可以纠错【光标停留在其ctrl+1】
*黄色下划线:警告,但可以编译
面向对象和面向过程的区别
面向对象和面向过程的区别
面向过程:具体过程,具体因果
优点:对于业务逻辑比较简单的程序,可快速开发,前期投入低
缺点:难以解决复杂业务逻辑,软件元素之间“耦合度"非常高,一环出问题,整个系统受到影响
"扩展力"差,没有"独立体"的概念,组件无法重复利用
面向对象:对象的【独立体】能完成那些功能。
优点:"耦合度"低,"扩展能力"强,容易解决复杂业务逻辑,组件复用性强
缺点:前期投入成本高,需要进行独立体的抽取
C语言是面向过程,c++半面向对象,java面向对象
面向对象符合人的思维
面向对象的三大特征
封装
上面的java修饰符,我们学到了private修饰符,java三大特性中的封装,和这个private修饰符息息相关。
先来说一下封装的思想。我们生活很多地方都用到了这个思想。我举一个可能不太恰当的例子,比如一台电视机,包含了很多物理元件,这些物理元件都被电视机的外壳“封装”起来,只给用户提供了电源键、菜单键、音量键等按钮。这样做有几个好处,一个是安全性,内部元件不被破坏,第二个是简单方便,用户不用了解电视机复杂的构造,凭借几个按钮就可以控制电视机。这就是封装的思想,把类里的定义的变量“隐藏”起来,不能直接访问和修改这些变量,只能通过特地的方法才能访问修改变量,保证了数据的安全性。
继承
接着说继承的思想。很多时候,很多东西都是用一些共同点的。比如现在需要写几个汽车的类,一个是宝马,一个是迈巴赫,一个是劳斯莱斯。然后写好后发现,几个类中很多属性都是重复的,毕竟车的总体结构都是差不多的。所以我们花费了很多时间,写了很多差不多一样的代码,我们的效率就很低下了,而且代码重复性高。为了提高效率和代码复用率,我们可以把这些相同的属性放到一个公共的类里,当成父类,具体的汽车类(比如迈巴赫类)继承这些相同的属性,再根据自身特点加入其他属性。这就是继承的思想,继承的特性可以使得代码变得简洁,并减少重复的代码。
另外,值得注意的是,父类中的私有属性和私有方法(即用private修饰的属性和方法)不能被子类继承,非私有的属性和方法子类都可以继承。再举个可能不那么恰当的例子:你爸爸藏了私房钱,这些钱你不知道,也没办法得到。(哈哈)
多态
我们可以用一种简单的思路来理解多态:
上面,我们讲了一种“is-a”规则。“Student is a Person”。
那么,我们可以将一个子类Student的对象的引用赋给父类类型的变量,即 Person p = new Student(); (这就是多态),这是很容易理解的:如果是学生,那么肯定是人。所以Person类变量引用student对象是完全没有问题的。但反过来就不行了,因为不是每一个人都是学生。所以子类变量不能引用父类对象(即使通过强制类型转换可以转换通过,但是使用过程中还是可能会出错,如调用子类自定义的的方法时)。
将子类对象的引用赋给父类变量: 要理解这句话,就要要区别变量和引用。变量是声明就可以了,比如 Person person,这样person就是一个变量,但是没有引用一个具体的对象(引用为空)。 Teacher teacher = new Teacher(“hello”,15); 这条语句中,定义了一个teacher变量,让teacher变量引用了一个具体的实例化对象。而多态就是 person =teacher ; 这里就把teacher引用的具体对象赋给person。
OOA,OOD,OOP
所有面向对象的编程语言都有这三大特征
用面向对象的方法开发软件,其生命周期中:
OOA:面向对象程序设计的分析
OOD:面向对象程序设计的设计
OOP:面向对象程序设计的编程
类和对象的概念
类和对象的概念
什么是类?
-类在现实世界不存在,是一个模板概念,是人类大脑抽象的结果
-类代表一类事物
-在现实中,对象A和对象B有共同特征,抽象总结的模板,称为类
什么是对象?
-对象是现实世界中实际存在的,
*描述一下整个软件的开发过程
抽象类
定义类
用类创建对象
象直接协作起来成为一个系统
类–【实例化】–对象
对象又被称为实力/instance
对象–【抽象】–类
*类描述的是对象的共同特征,必须先创建对象,通过对象访问特征,
*一个类主要描述什么信息?
状态+动作
*类
{
属性:状态
方法:动作
}
状态和动作具体后结果可以不一样。
类的定义【开始编写代码】
语法结构:
[修饰符列表]class 类名{
}
学生类,所有学生对象的共同特征
状态信息:
学号
姓名
性别
年龄
住址
动作:
吃饭
学习
*属性用一个变量的形式定义,
*java中两种数据类型
-基本数据类型
-引用数据类型
类名 变量名;
String
System
Student
类的定义
java语言是纯面向对象
定义类:
【修饰符列表】 class 类名{
属性:
方法:
}
属性通常采用变量来表示,有数据类型
【基本数据类型+引用数据型】
属性对应状态信息
以商店商品为例:商品有共同特征:单价,编号
对象的创建和使用
一个类可以创建N个对象
创建对象的语法:new 类名();
new是java语言中的运算符
new创建对象,在JVM堆中开辟新的空间
方法区内存:在类的加载中,class字节码代码片段加载到该空间中
栈内存(局部变量):方法代码片段执行时,会给该方法分配内存空间,在栈中压栈
堆内存:new的对象在堆内存中存储
什么是对象?
new 运算符在堆内存中开辟的空间
什么是引用?
s 是一个变量,保存了一个Java对象的内存地址
程序员不能直接操作内存,只能通过“引用”去访问对内存中的对象的实例变量
*局部变量在栈中存出
*成员变量中的实例变量在堆内存的java对象内部存储
实例对象是以个对象一份
对象操作中的空指针异常
Exception in thread “main” java.lang.NullPointerException
at OOTest.main(OOTest.java:14)
空指针异常
编译可通过,运行出错
空引用访问“实例“相关数据会出现空指针异常
java.lang.NullPointerException
“实例“相关数据标识:这个数据访问的时候必须有对象参与
public static void main(String[] args){
RecursionTest r = new RecursionTest();
Student s = new Student();
System.out.println(s.rt.method(5));
/*
Student s = new Student();
s.id = 195769;
System.out.println(s.id);
RecursionTest r = new RecursionTest();
System.out.println(r.method(5));
*/
}
}
JVM内存管理
详细介绍:link
参数传递
方法调用时,参数传递的时候,java只遵循一种语法机制 就是将变量中保存的“值”传递过去,这个值可以是具体指也可以是变量
public class Test01 {
public static void main(String[] args) {
User u = new User(12);
//(引用是地址传递,u中保存的值是对象的地址,传递内容是地址)其实还是值传递
add(u);
System.out.println("main-->" + u.age);
}
public static void add(User u) {
u.age++;
System.out.println("add-->" + u.age);
}
}
class User {
int age;
User(int a) {
age = a;
}
}
面向对象的封装性
1、封装的概念:
将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。
2、好处:
(1)只能通过规定的方法访问数据
(2)隐藏类的实例细节,方便修改和实现。
3、封装的实现步骤
(1)修改属性的可见性设为(private)
(2)创建getter/setter方法(用于属性的读写)(通过这两种方法对数据进行获取和设定,对象通过调用这两种发方法实现对数据的读写)
(3)在getter/setter方法中加入属性控制语句(对属性值的合法性进行判断)
对于当前程序员来说: User类中的age属性在外部可以随意访问,导致age属性不安全。
User对象表示一个用户时,用户的年龄不可能为负数,要有报错机制
面向对象三大特征:
-封装(当前进行)
-继承
-多态
为什么要封装?封装的好处?
1、封装置后对于事物来说,看不到复杂的那一面,只能看到简单的那一面。
复杂性封装,对外提供简单入口。操作简单便捷,不需要关心内部实现原理。
2、封装后才会形成“对象”,真正的“独立体”。
3、封装后意味着程序以后可以重复着使用,事物的适应性较强,在任何场所都可以使用,
4、封装之后,对于事物本身,提高安全性。【安全性高】
面向对象的继承
java 中的继承:
1、面向对象三大特征之一
2、作用:代码复用。
有了继承才有以后的“方法的覆盖”和“多态机制” 。
3、继承语法:
【修饰符列表】 class 类名 extends 父类名{
类体=属性+方法;
}
4、java只支持单继承,只能继承一个类
5、继承术语:
B类继承A类
A类称为:父类,基类,超类,superclass
B类 :子类,派生类,subclass
6、在Java中那些可以继承
私有类不可继承
构造方法不可继承
其他都可继承
7、一个类可以间接继承其他类
8、java没有显示继承类就会默认继承JavaSE库中的java.lang.Object类
面向对象的多态
1、java中的多态
2、 面向对象的核心:
定义好类,然后将类实例化为对象,给一个环境让类驱使
使各个对象成为一个系统。
3、多态在开发中的作用?
降低程序的耦合度,提高程序的拓展力
父类型引用指向子类型对象
核心:面向抽象编程,不要面向具体编程。
强制类型转换 概念(类型之间必须有继承
向上转型:(upcasting
子类型–>父类型
自动类型转
向下转换:(downcasting
父类型–>子类型
强制类型转换
4、Java语法:父类型引用指向子类型对象
public class Test {
public static void main(String[] args) {
Animal al = new Animal();
al.doSome();
Cat c = new Cat();
c.doSome();
Bird b = new Bird();
b.doSome();
Animal a2 = new Cat();
/**
* 1、java 程序分为编译和运行
* 2、先编译,后运行。
* 3、编译阶段编译器检查引用数据类,编译通过,这个
* 过程就成为静态绑定,编译阶段绑定。编译阶段绑定成
* 功后才能运行。
* 4、在程序运行阶段,JVM堆内存中真实对象是Cat对象
* 是它继承的方法,此时发生了动态绑定,进行阶段绑定。
* 5、无论Cat类有没有doSome方法,运行阶段一定调用
* Cat对象doSome方法,底层真实对象就是Cat对象。
* 6、:父类型引用指向子类型对象这种机制存在编译绑定
* 和运行绑定两种不同的形态/状态,即一种语法多态机制。
*
*
*/
a2.doSome();
/**
* 想要a2.catchMouth();也执行该怎么办?
* 强制类型转换
* 需求:两种类有继承关系
*
* 什么时候需要向下转型?
* 当调用的方法是子类型特有的,需要进行向下转换。
*
*/
Cat c2 = (Cat)a2;
c2.catchMouth();
Animal a3 = new Bird();
/**
* 1、以下程序在编译期没有错误,因为检查a3的类型Animal
* Animal和Cat之间有继承关系,父类型向下转换,语法合法。
*
* 2、但是程序在运行的时候会出现异常,因为JVM堆内存
* 当中真实存在的对象实Bird类型,Bird对象无法转换成
* Cat对象,两种类之间不存在继承关系,因此出现异常:
* java.lang.ClassCastExceotion
* 类型转换异常,总是在向下转型中发生。
*
* 3、向下转型存在隐患(编译通过,运行报错)
* 4、使用instanceof运算符可以避免以上异常
* 5、instanceof用法?
* 语法格式:
* (引用 instanceof 数据类型)
* 以上运算符执行结果是布尔类型,true/false
* 假设(a instanceof Animal)
* true 表示a引用指向对象实Animal
*
* false 表示a引用指向对象不是Animal
*
* 6、java规范要求:在进行强制类型转换前要采用instanceof
* 判断。
*
*/
//只有当访问子类中特有的方法才有如下代码
if(a3 instanceof Cat){
Cat c3 = (Cat)a3;//只在编译合法,运行会debug
c3.catchMouth();
}
else if(a3 instanceof Bird){
Bird b2 = (Bird)a3;
b2.fly();
}
}
}
this 关键字
java中的this关键字:
1、this:这个
2、this是一个变量,其中保存了内存地址指向自身,this
存储在JVM堆内存java对象的内部。
3、创建100个java对象就有100个不同的this
4、this可以出现在实例方法中,代指执行这个动作的对象。
5、this不能在带有static的方法中使用
this什么时候不能省略?
用来区分局部变量和实例变量的时候
this.实例变量 = 局部变量;
1、可在实例方法中代表当前对象【this.实例变量】
2、可以用在构造方法中通过当前的构造方法调用其他
构造方法,【this();】
this();这种语法只能出现在构造函数的第一行。
this在构造函数中调用其他构造函数为实例变量赋值
public class User {
private int id;
private String name;
public User() {
// this.id = 100;
// this.name = "dfghjk";
// 以上代码可以通过调用另一个构造方法来完成
// 但是前提是不能创建新的对象,下面这行代码可以完成初始化
this(11, "ghjkl");
System.out.println("this!!");
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
static 关键字
方法什么时候定义为静态的?
所有对象都执行这个动作,最终产影响一样时。
静态方法无法直接访问实例变量和实例方法 。
一般工具类都定义为静态方法,为了方便调用,
最好不用new大对象调用。
静态代码块
(还有实例代码块,{java语句;} 其在构造方法执行之前执行,特殊时刻:构造方法执行之前即new的时候!
1、语法:
static{
java语句;
}
4、作用是什么?怎么用?在哪?什么时候?
-与具体要求有关,项目要求在类加载时刻/时机执行代码完成
日志的记录。那么这段代码就可以写到静态代码块内,完成要求。
-类加载时刻执行。
5、通常在静态代码块中完成预备工作,数据准备,
this可以使用在哪里?
public class Customer {
String name;
public Customer() {
super();
}
// 不带static的方法
// 购物行为最终结果不同
// 购物行为是对象级别行为,需要对象参与
// *没有static关键字的方法称为“实例方法”,访问:引用.方法名
// 变量称为“实例变量” :引用.变量名
// 当一个行为/动作执行时需要对象参与时,这个方法要定义为“实例方法”不要带static关键字
//
public void shopping() {
// 下面name省略了引用,但是语法要求访问实例变量要
// 引用.变量名,所以此处可以加上this
// System.out.println(name+"正在购物!");
// 完整写法
//this可以省略(多数情况下)
System.out.println(this.name + "正在购物!");
}
// 这个方法调用不需要对象,类名.方法名可访问
// 上下文中没有当前对象,不存在this(
// 为什么报错?
// doSome是一个类名调用,
// name是一个实例变量,以下代码含义:访问当前对象的name
// 没有当前对象自然不能访问当前对象的name
public static void doSome() {
// static方法调用不需要对象
// System.out.println(this);
// System.out.println(name);
// 怎么访问name?
// 创建对象!
// 但是创建对象访问的不是当前对象的内容
// Customer c = new Customer();
// System.out.println(c.name);
}
}
final 关键字
java 中final关键字:
1、final是一个关键字
2、final修饰类无法被继承
3、final修饰的方法无法被覆盖
4、final修饰的变量一旦赋值,不能更改
5、修饰实例变量,实例变量有默认值,不能更改,实例变量
用final必须手动赋值,或者是在构造方法内赋值,都是在构造
方法执行过程中给final修饰实例变量赋值。
6、修饰引用不能指向其他对象,被指向对象无法回收,但是
这个对象内部是可以修改的
7、修饰实例变量,一般与static连用,成为常量;
关于myeclipse怎么链接原码:
点击 Attached Aource
-workplace 【源码在当前工作区中】
-External File……【源码在某个压缩文件中】
-External Folder……【源码在某个目录中】
对于类库,一般是由三个部分:
-源码【理解程序
-字节码【开发过程中使用的就是这部分
-帮助信息【对开发提供帮助文档
常量的定义:
public static final 数据类型 常量名 = 值;
java中要求常量名大写每个单词用下划线连接
public static final country = "中国";
访问权限控制修饰符
1、访问控制权修饰符控制元素访问范围
2、包括:
public 公开的在任何位置都可以访问
protected 同包,子类
缺省 同包
private 私有,只能在本类中访问
3、可修饰类、方法、变量
4、默认缺省修饰
5、范围排行
public>protected>缺省>private
6、类只能用public和缺省修饰
构造函数
java类中的构造方法
1、构造方法又称为构造函数/构造器/Constructor ;
2、构造方法语法:
【修饰符列表】 构造方法名(形式参数表){
构造方法体; };
4、对于构造方法体来说,返回值类型不需要指定,不能写void ;
5、对于构造方法的方法名来说必须与类名完全相同;
6、构造方法的作用? 存在意义,通过构造方法的调用,可以创建对象。;
7、构造方法怎么调用? ;
-普通方法调用:类名.方法名()【有static修饰】 or 引用.方法名()
-new 构造方法名(是参列表);
8、构造方法调用有返回值吗?;
每一个构造方法结束都有返回值,不需要写return。;
并且返回值类型是构造方法所在类的类型。;
由于构造方法的返回值类型就是类本身 所以不需要写返回值类型;
9、注释快捷键 :单行ctrl+/ 多行ctrl+shift+/;
10、 当一个类中没有构造方法,系统默认提供无参数构造方法,称为缺省构造器
11、一个类将构造方法定义出来,系统不再提供缺省构造器,需要自己写无参构造函数
12、同一个类中构造函数可以重载
构造方法的作用:
1、创建对象
2、初始化实例变量的内存空间【给实例变量赋值】
成员变量之实例变量,属于对象级别的变量,这种变量必须先有对象才能有
实例变量实例变量没有手动赋值的时候,系统默认赋值,而实例变量的内存
空间是在构造方法执行过程当中开辟的,完成初始化的。
实例变量是存储子在JVM 的堆内存,new 的时候才会被赋值
public static void main(String[] args) {
//创建User对象
//调用User类的构造方法来完成对象创建
//只有方法名才带括号,所以User()显然是一个方法。
new User(1);
new User('s');
new User("dfghjkl;");
}
}
方法的重写/覆盖
**java中的重载:**功能相似,方法名相同
程序员在使用相似方法是就像在用一个似的,【JavaScript不支持】
1、Overload
2、什么时候考虑方法重载?
3、什么条件构成方法重载?
*在同一个类
*方法名不同
*参数列表不同
-数量
-顺序
-类型
4、方法重载方法重载和什么有关系,和什么没关?
*方法重载和方法名+参数列表有关
*方法重载和返回值类型,修饰符列表无关
public class OverloadTest{
public static void main(String[] args){
System.out.println(sum(1,2));
System.out.println(sum(1.9,2.0));
System.out.println(sum(1L,2L));
}
public static int sum(int a,int b){
System.out.println("int");
return a+b;
}
public static long sum(long a,long b){
System.out.println("long");
return a+b;
}
public static double sum(double a,double b){
System.out.println("double");
return a+b;
}
}
java中方法的覆盖:
1、又称为方法的重写,override【官方】/overwrite
2、什么时候方法重写?
父类中的方法无法满足子类业务要求
子类将父类中方法重写
这个过程称为方法重写
3、什么条件满足之后会发生方法重写?
发生在继承关系的父子类之间,
public static void main(String[] args)完全相同,一般粘贴
访问权限可以更高,不能低
抛出异常不可以更多,可能少
4、粘贴方法,在重写
5、私有方法和构造方法不能继承,所以不能覆盖
静态方法不存在覆盖,【多态时会讲】
覆盖只针对方法,不涉及属性
实现下列要求为例:
主人类(主人有喂养宠物的动作)
宠物类
狗类(吃骨头的动作)
猫类(吃鱼的动作)
主人喂狗
主人喂猫
主人喂蛇(更新内容)
//操作入口代码
public class Test {
public static void main(String[] args) {
Master m = new Master();
Cat c = new Cat();
m.feed(c);
Dog d = new Dog();
m.feed(d);
}
}
//降低程序的耦合度,可以提高拓展力。
//面向抽象对象编程 :宠物
public class Master{
public void feed(Pet pet){
pet.eat();
}
}
//下面方法的拓展力较差,因为面向了具体对象编程: 猫、狗
/*public class Master {
public void feed(Cat c) {
c.eat();
}
public void feed(Dog d) {
d.est();
}
}
*/
public class Pet {
//宠物可以吃东西
public void eat(){
}
}
public class Cat extends Pet{
public void eat() {
System.out.println("猫在吃鱼!!");
}
}
public class Dog extends Pet{
public void eat() {
System.out.println("狗在啃骨头!!");
}
}
包机制package和引入import
关于java的包机制:
1、包又称为package,java中引入包机制方便文件管理。
2、怎么定义package?
-java在代码首行
-package只能编写一行代码
-语法:
package 包名;
3、包名规范:
公司域名倒叙.项目名.模块名.功能名
4、包名全部小写,标识符命名规则
5、一个包对应一个目录
6、使用包名后,怎么编译,怎么运行?
-使用包名后,类名不再是day11,类名是包名.day11
编译: javac源文件路径(生成.class文件
运行:手动创建目录,将.class文件放到目录下
另一种方式:javac -d . *.class
解释:将当前目录下所有java文件编译后放置到指定目录下
运行:JVM的类加载器ClassLosder默认从当前路径下加载
保证DOS窗口的路径切换到com所在路径,执行:
java com.sdfghjk.fghjk.day11.test01
7、 什么时候包名可以省略?
类在同一目录下时。
import 导入!
语法:
package下一行class之上
import 包名.*;
lang包不需要引入,时java的核心类。
import java.util.Data;
不是lang包下的类和同一个目录下的类需要引入!
导入类的快捷键:
ctrl shift o