Java 基础总结

目录

一 Java概述

Java特性

环境变量配置

Java学习方法

Java转义符

初学易犯错误

注释

二、变量

变量基本原理、概念

程序中 + 号的使用

数据类型(背)

Int类型使用细节

浮点型与浮点型使用细节

JAVA API文档

字符类型char、char细节

字符本质探讨、字符编码

布尔类型boolean

Java自动转换+细节(背)

强制类型转换、细节

基本数据类型与String的转换 

基本数据类型与String转换细节

三 运算符

算术运算符

取模运算

除法 /

关系运算符

逻辑运算符

赋值运算符

三元运算符

运算符优先级(多用,别刻意背)

标识符的命名规则和规范

命名规范

键盘输入

进制(程序员基本功)

进制转换

二进制在运算中的说明

原码 反码  补码(重点. 难点)  背下来

位运算符

第四章 程序控制结构

分支结构

If-else结构

Switch分支结构

Switch注意事项与细节

循环结构

for循环

For细节和注意事项

编程思想(理解 练习)

While循环

Do while循环

Do while注意事项

多重循环控制(重点!难点!)

Break语句

跳转控制语句 – continue

跳转控制语句-return

六 数组

简介

数组的使用

数组细节、默认值

数组赋值机制 (理解 背)

数组拷贝

数组反转 添加/扩容

二维数组

二维数组赋值机制(重要)

初始化方式

七、面向对象编程(基础部分)

简介  引出

类与对象关系示意图

对象在内存中存在形式(重要的)必须搞清楚

属性/成员变量/字段  细节、注意事项

类与对象

 类和对象的内存分配机制(重要)

成员方法

方法的调用机制原理图  重要

成员方法注意事项和使用细节(重要)

方法调用细节说明(重要!)

成员方法传参机制(非常非常重要

方法递归调用

递归重要规则

方法重载

重载注意事项和使用细节

可变参数

作用域

作用域使用细节和注意事项(背)

构造方法/构造器

构造器使用细节和注意事项

对象创建的流程分析(自己模拟画一遍)

this关键字

this 的注意事项和使用细节

匿名对象

八、面向对象编程(中级部分)

IDEA(集成开发环境)

模板/自定义模板

包的本质分析(原理)

包的注意事项和细节

访问修饰符

四种访问修饰符的访问范围和注意事项( 重要 背下来)

面向对象编程-封装

面向对象编程-继承(extends)

继承基本介绍和示意图

继承的基本语法

继承的深入讨论/细节问题(重要)

继承的本质讨论 / 子类创建的内存布局(重要)

super关键字

super 给编程带来的便利/细节

Super和 this 的比较

方法重写/覆盖(override)

注意事项和使用细节

方法重载与方法重写 比较



一 Java概述

Java特性

跨平台

跨平台的根本原因:jvm

环境变量配置

理解:2.告诉计算机我的jdk安装目录

     3.告诉计算机到java_home下的bin目录去找运行的指令

命令行编译乱码及解决

设置文件的编码与控制台一样再保存

运行的是study这个类,而不是study.class这个文件,所以不带.class

Java运行过程

注意事项

6.编译后每一个类都对应的生成一个.class文件

第八点

Java学习方法

第六条永无止境

Java转义符

控制台用Tab键:自动补齐

重点区分换行和回车

换行 \n:  光标调到下一行

回车 \r:光标回到句首

初学易犯错误

注释

多行注释不能嵌套

文档注释(用得挺多的)

可以用命令生成说明文档

代码规范

Dos指令(了解)

相对路径绝对路径

二、变量

变量基本原理、概念

变量是程序的基本组成单位

变量两种初始化:1)先声明,在赋值。2)声明的同时直接赋值(初始化)

程序中 + 号的使用

数据类型(背)

这几个背下来

Int类型使用细节

浮点型与浮点型使用细节

浮点型的陷阱!!

//浮点型数据做运算后不能直接比较,因为内存里存的都是近似值,

//做运算后得到的也是近似值

可以按需要规定一个相差范围。满足即认为两个数相等

如果是直接查询或者直接赋值得到的小数,是可以直接判断相等的

JAVA API文档

字符类型char、char细节

字符类型可以表示单个字符,字符类型是 char,char 是两个字节(可以存放汉字),多个字符我们用字符串String

字符细节

字符本质探讨、字符编码

常见字符编码介绍

布尔类型boolean

在java中

Java自动转换+细节(

背!

自动转换细节.

细节4:byte、short、char他们三者不管是相互运算还是混合运算结果都是 int

强制类型转换、细节

谨慎!谨慎使用

强制类型转换细节

基本数据类型与String的转换 

charAt()是字符串类型的一个方法,是返回字符串指定索引位置的字符。(只能从字符串中截取)

基本数据类型与String转换细节

三 运算符

算术运算符

介绍

取模运算

本质

除法 /

关系运算符

逻辑运算符

分析方法

1) 短路与 && , 短路或 ||,取反 !

 2) 逻辑与 &,逻辑或 |,^

ü 说明逻辑运算规则:

1) a&b : & 叫逻辑与:规则:当 a 和 b 同时为 true ,则结果为 true, 否则为 false

2) a&&b : && 叫短路与:规则:当 a 和 b 同时为 true ,则结果为 true,否则为 false

3) a|b : | 叫逻辑或,规则:当 a 和 b ,有一个为 true ,则结果为 true,否则为 false

4) a||b : || 叫短路或,规则:当 a 和 b ,有一个为 true ,则结果为 true,否则为 false

5) !a : 叫取反,或者非运算。当 a 为 true, 则结果为 false, 当 a 为 false 是,结果为 true

6) a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为 true, 否则为 false

//看看区别 :

(1)||短路或:如果第一个条件为 true, 则第二个条件不会判断,最终结果为 true,效率高

(2)| 逻辑或:不管第一个条件是否为 true,第二个条件都要判断,效率低

赋值运算符

复合赋值运算会进行强制类型转换  ,如

复合赋值运算细节

1) 运算顺序从右往左 int num = a + b + c;

2) 赋值运算符的左边 只能是变量,右边 可以是变量、表达式、常量值 int num = 20; int num2= 78 * 34 - 10; int num3 = a;

3) 复合赋值运算符等价于下面的效果 比如:a+=3;等价于 a=a+3; 其他类推

4) 复合赋值运算符会进行类型转换。 byte b

三元运算符

4.6.1基本语法

条件表达式 ? 表达式 1: 表达式 2;

运算规则:

1. 如果条件表达式为 true,运算后的结果是表达式 1;

2. 如果条件表达式为 false,运算后的结果是表达式 2;

口诀: [一灯大师:一真大师]

细节

运算符优先级(多用,别刻意背)

标识符的命名规则和规范

命名规范

1) 包名:多单词组成时所有字母都小写:aaa.bbb.ccc //比如 com.hsp.crm

2) 类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz [大驼峰]

比如: TankShotGame

3) 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz [小驼峰, 简称 驼峰法]

比如: tankShotGame

4) 常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ

比如 :定义一个所得税率 TAX_RATE

5) 后面我们学习到 类,包,接口,等时,我们的命名规范要这样遵守,更加详细的看文档.

键盘输入

System.in代表从键盘输入

4.11.1 介绍

在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。Input.java , 需要一个 扫描器(对象), 就是

Scanner

4.11.2 步骤 :

1) 导入该类的所在包, java.util.*

2) 创建该类对象(声明变量)

3) 调用里面的功能

进制(程序员基本功)

介绍

对于整数,有四种表示方式:

二进制:0,1 ,满 2 进 1.以 0b 或 0B 开头。

十进制:0-9 ,满 10 进 1。

八进制:0-7 ,满 8 进 1. 以数字 0 开头表示。

十六进制:0-9 及 A(10)-F(15),满 16 进 1. 以 0x 或 0X 开头表示。此处的 A-F 不区分大小写.

图示

进制转换

 第一组:

  1. 二进制转十进制

  1. 八进制转十进制

  1. 十六进制转十进制

规则:从最低位(右边)开始,将每个位上的数提取出来,乘以 16 的(位数-1)次方,然后求和。

案例:请将 0x23A 转成十进制的数

0x23A = 10 * 16^0 + 3 * 16 ^ 1 + 2 * 16^2 =

 第二组:

  1. 十进制转二进制

规则:将该数不断除以 2,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。

案例:请将 34 转成二进制 = 0B0010001

  1. 十进制转八进制

规则:将该数不断除以 8,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的八进制。 案例:请将 131 转成八进制 => 0203

  1. 十进制转十六进制

规则:将该数不断除以 16,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的十六进制。 案例:请将 237 转成十六进制 => 0xED

 第三组

  1. 二进制转八进制

规则:从低位开始,将二进制数每三位一组,转成对应的八进制数即可

  1. 二进制转十六进制

从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。

 第四组

  1. 八进制转二进制

从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。

  1. 十六进制转二进制

规则:将十六进制数每 1 位,转成对应的 4 位的一个二进制数即可

二进制在运算中的说明

原码 反码  补码(重点. 难点)  下来

位运算符

还有 3 个位运算符 >>、<< 和 >>> , 运算规则:

1) 算术右移 >>:低位溢出,符号位不变,并用符号位补溢出的高位

2) 算术左移 <<: 符号位不变,低位补 0

3) >>> 逻辑右移也叫无符号右移,运算规则是: 低位溢出,高位补 0

4) 特别说明:没有 <<< 符号

   Chaper04: BitOperator.java  BitOperator01.java

Tip:

  1. 溢出就是扔掉的意思
  2. >>算术右移本质: 移动一位就相当于除以一个2( <<同理 )

第四章 程序控制结构

分支结构

If-else结构

单分支

双分支

多分支

细节:多分支结构找到一个执行入口后,后面的分支就不再判断了

多分支的流程图

嵌套分支

在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。老师建议: 不要超过 3 层 (可读性不好)

Switch分支结构

Default后面有没有break都会退出switch.

基本语法

Switch流程图(理解)

Switch注意事项与细节

If-else与switch的选择

循环结构

for循环

基本语法

流程图

For细节和注意事项

内存分析

死循环

编程思想(理解 练习)

//老韩的两个编程思想(技巧)

1. 化繁为简 : 即将复杂的需求,拆解成简单的需求,逐步完成 编程 = 思想 --练习-> 代码

2. 先死后活 : 先考虑固定的值,然后转成可以灵活变化的值

While循环

基本语法

流程图

内存分析图

While注意事项和细节

1) 循环条件是返回一个布尔值的表达式

2) while 循环是先判断再执行语句

Do while循环

基本语法

老韩说明:

1. do while 是关键字

1. 也有循环四要素, 只是位置不一样

2. 先执行,再判断,也就是说,一定会至少执行一次

3. 最后 有一个 分号 ;

4. while 和 do..while 区别举例:

流程图

Do while注意事项

1) 循环条件是返回一个布尔值的表达式

2) do..while 循环是先执行,再判断, 因此它至少执行一

多重循环控制(重点!难点!)

1) 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while 均可以作为外层循环和内层循环。

【建议一般使用两层,最多不要超过 3 层, 否则,代码的可读性很差】

2) 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为 false 时,才会完全跳出内

层循环,才可结束外层的当次循环,开始下一次的循环[听不懂,走案例]。

  1. 设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n次

请分析 下面的多重循环执行步骤, 并写出输出 => 韩老师的内存分析法

//双层 for MulFor.java

for(int i = 0; i < 2; i++) { //先思考

for( int j = 0; j < 3; j++) {

System.out.println("i=" + i + j=" + j);

}

}

Break语句

跳转控制语句 – continue

基本介绍:

1) continue 语句用于结束本次循环,继续执行下一次循环。

2) continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这个和前面的标签的

使用的规则一样

流程图

跳转控制语句-return

Return使用在方法中, 表示退出所在方法,  若使用在main方法中,则代表退出程序

六 数组

简介

数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。 即:数(数据)组(一组)就是一组数据

定义

Int[ ] array = {…}  等价于  int array[ ] = {…}

数组的使用

使用方式1 : 动态初始化

使用方式 2-动态初始化

 先声明数组

语法:数据类型 数组名[]; 也可以 数据类型[] 数组名;

int a[]; 或者 int[] a;

 创建数组

语法: 数组名=new 数据类型[大小];

a=new int[10]

示例:

第 2 种动态分配方式, 先声明数组,再 new 分配空间

double scores[] ; //声明数组, 这时 scores 是 null

scores = new double[5]; // 分配内存空间,可以存放数据

使用方式3:静态初始化

数组细节、默认值

数组使用注意事项和细节

1) 数组是多个相同类型数据的组合,实现对这些数据的统一管理

2) 数组中的元素可以是任何数据类型,包括基本类型和引用类型,但是不能混用。

3) 数组创建后,如果没有赋值,有默认值

int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null

  1. 使用数组的步骤 1. 声明数组并开辟空间 2 给数组各个元素赋值 3 使用数组

注: // 任何一个办法声明后java内存里面分配好了地址了已经,所以不能同时使用静态和动态初始化。java只分配一次内存

如 : int[] a = new int[6];   a = {1,2,3,4,5,6};  错!

5) 数组的下标是从 0 开始的。

6) 数组下标必须在指定范围内使用,否则报:下标越界异常,比如

int [] arr=new int[5]; 则有效下标为 0-4

7) 数组属引用类型,数组型数据是对象(object)

数组赋值机制 (理解 背)

1) 基本数据类型赋值,这个值就是具体的数据,而且相互不影响。

int n1 = 2; int n2 = n1;

2) 数组在默认情况下是引用传递,赋的值是地址。

看一个案例,并分析数组赋值的内存图(重点, 难点. )。

//代码 ArrayAssign.java

int[] arr1 = {1,2,3};

int[] arr2 = arr1;

在内存中,只要分配了一个数据空间,就一定会对应一个地址

基本数据类型: 值传递,各自有存储空间

引用数据类型: 址传递(引用传递),指向同一块存储地址

数组拷贝

将 int[] arr1 = {10,20,30}; 拷贝到 arr2 数组, 要求数据空间是独立的.

每个数组都有独立的空间

数组反转 添加/扩容

数组添加/扩容

要求:实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java

1) 原始数组使用静态分配 int[] arr = {1,2,3}

2) 增加的元素 4,直接放在数组的最后 arr = {1,2,3,4}

3) 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n

//总结

       // 1.数组是引用类型,他指向一个内存空间

       // 1.1所以无论两个数组之间长度相差多少,都可以直接赋值 , 因为他仅仅是改变一个地址,原来的空间会被回收

二维数组

二维数组赋值机制(重要

二维数组不直接指向数据

它先指向一个空间,这个空间存放的是一维数组的地址,然后再指向一个真正存放数据的空间

初始化方式

:动态初始化1

TwoDimensionalArray02.java

1) 语法: 类型[][] 数组名=new 类型[大小][大小]

2) 比如: int a[][]=new int[2][3]

动态初始化2

先声明:类型 数组名[][]; TwoDimensionalArray02.java

再定义(开辟空间) 数组名 = new 类型[大小][大小]

赋值(有默认值,比如 int 类型的就是 0

动态初始化3:列数不确定 TwoDimensionalArray03

原理图

使用方式 4: 静态初始化

TwoDimensionalArray04.java

定义 类型 数组名[][] = {{值 1,值 2..},{值 1,值 2..},{值 1,值 2..}}

使用即可 [ 固定方式访问 ]

比如:

int[][] arr = {{1,1,1}, {8,8,9}, {100}};

解读

  1. 定义了一个二维数组 arr

2. arr 有三个元素(每个元素都是一维数组)

3. 第一个一维数组有 3 个元素 , 第二个一维数组有 3 个元素, 第三个一维数组有 1 个元素

注: 第三个一维数组的括号不能省略 ,否则类型不匹配, 如:

int[][] arr = {{1,1,1}, {8,8,9}, 100};

七、面向对象编程(基础部分)

简介  引出

7.1 类与对象

7.1.1看一个养猫猫问题

张老太养了两只猫猫:一只名字叫小白,今年 3 岁,白色。还有一只叫小花,今年 100 岁,花色。请编写一个程序,当用户

输入小猫的名字时,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示 张老太没有这只猫猫。

7.1.2使用现有技术解决 Object01.java

1) 单独的定义变量解决

2) 使用数组解决

7.1.3现有技术解决的缺点分析

不利于数据的管理

效率低===》 引出我们的新知识点 类与对象 哲学, 道家思想

java 设计者 引入 类与对象(OOP) ,根本原因就是现有的技术,不能完美的解决新的新的需求

类与对象关系示意图

类和对象的区别和联系

1) 类是抽象的,概念的,代表一类事物,比如人类,猫类.., 即它是数据类型.

2) 对象是具体的,实际的,代表一个具体事物, 即 是实例.

3) 类是对象的模板,对象是类的一个个体,对应一个实例

对象在内存中存在形式(重要的)必须搞清楚

解读:

1.基本数据类型直接放在堆中

2.引用数据类型在堆中存放的是地址,实际内容存放在方法区中的常量池中

3.创建对象的时候会把类的信息加载到方法区

属性/成员变量/字段  细节、注意事项

介绍

  1. 从概念或叫法上看: 成员变量 = 属性 = field(字段) (即 成员变量是用来表示属性的,授课中,统一叫 属性
  2. 属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类 的 int age 就 是属性

注意事项和细节说明

PropertiesDetail.java

1) 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;

这里老师简单的介绍访问修饰符: 控制属性的访问范围

有四种访问修饰符 public, proctected, 默认, private ,后面我会详细介绍

2) 属性的定义类型可以为任意类型,包含基本类型或引用类型

3) 属性如果不赋值,有默认值,规则和数组一致。具体说: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null

真正的对象是堆里面分配的空间(包括方法区的常量池),cat只是指向那个对象而已

Cat只是对象的引用(对象名而已)

例如小明不是一个人,只是个名字(代号)。真正的主体是生出来的那个玩意

类与对象

如何创建对象

1) 先声明再创建

Cat cat ; //声明对象 cat

cat = new Cat(); //创建

2) 直接创建

Cat cat = new Cat();

 如何访问属性

 基本语法

对象名.属性名;

案例演示赋值和输出

cat.name ;

cat.age;

cat.color;

类和对象的内存分配机制(重要)

Java 内存的结构分析

1) 栈: 一般存放基本数据类型(局部变量)

2) 堆: 存放对象(Cat cat , 数组等)

3) 方法区:常量池(常量,比如字符串), 类加载信息

4) 示意图 [Cat (name, age, price)]

Java 创建对象的流程简单分析

Person p = new Person();

p.name = “jack”;

p.age = 10

1) 先加载 Person 类信息(属性和方法信息, 只会加载一次)

2) 在堆中分配空间, 进行默认初始化(看规则)

3) 把地址赋给 p , p 就指向对象

4) 进行指定初始化, 比如 p.name =”jack”

看一个示例分析

成员方法

快速入门: Method01.java

为什么需要成员方法

Method02.java

 看一个需求:

请遍历一个数组 , 输出数组的各个元素值。

 解决思路 1,传统的方法,就是使用单个 for 循环,将数组输出,大家看看问题是什么

解决思路 2: 定义一个类 MyTools ,然后写一个成员方法,调用方法实现,看看效果又如何

5成员方法的好处

1) 提高代码的复用性

2) 可以将实现的细节封装起来,然后供其他用户来调用即可

方法的调用机制原理图  重要

提示:画出程序执行过程[getSum]+说明

注:上面的getSum栈是为了方便讲解取的名,实际在底层没有这种叫法

成员方法定义

访问修饰符 返回数据类型 方法名(形参列表..) {//方法体 语句; return 返回值; }

  1. 形参列表:表示成员方法输入 cal(int n) , getSum(int num1,)

2) 返回数据类型:表示成员方法输出, void 表示没有返回值

3) 方法主体:表示为了实现某一功能代码块

4) return 语句不是必须的。

5) 老韩提示: 结合前面的题示意图, 来理解

成员方法注意事项和使用细节(重要)

/chaper/ MethodDeatail.java、MethodDetail02.java

访问修饰符 (作用是控制 方法使用的范围)

如果不写默认访问,[有四种: public, protected, 默认, private], 具体在后面

返回数据类型

1) 一个方法最多有一个返回值 [思考,如何返回多个结果 返回数组 ]

2) 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)

3) 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值; 而且要求返回值类型必须和 return 的

值类型一致或兼容

4) 如果方法是 void,则方法体中可以没有 return 语句,或者 只写 return

方法名

遵循驼峰命名法,最好见名知义,表达出该功能的意思即可, 比如 得到两个数的和 getSum, 开发中按照规

形参列表

  1. 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开,如: getSumI(int n ,int m)
  2. 参数类型可以为任意类型,包含基本类型或引用类型。比如 printArr(int[][] map)
  3. 调用带参数的方法时,一定要对应着参数列表传入相同类型或兼容类型的参数
  4. 方法定义是的参数为形式参数,简称形参;方法调用是的传入参数成为实际参数,简称实参,实参和形参的类型要一致或兼容、个数、顺序必须一致!   

方法体

 里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能在定义方法!

即:方法不能嵌套定义

方法调用细节说明(重要!)

MethodDetail02.java

  1. 同一个类中的方法调用:直接调用即可。比如:print(参数)

案例演示:A类sayOk 调用 print()

  1. 跨类中的方法A类调用B类方法:通过对象名调用。比如:对象名.方法名(参数);

案例演示:B类sayHello调用parint()

  1. 特别说明:跨类的方法调用和方法的访问修饰符相关。将到访问修饰符是回细说

成员方法传参机制(非常非常重要

基本数据类型的传参机制   chaper07/ MethodParameter01.java

结论:基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参

引用数据类型的传参机制  MethodParameter02.java

1) 看一个案例 MethodParameter02.java

B 类中编写一个方法 test100,可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化?会变化

B 类中编写一个方法 test200,可以接收一个 Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变化?   会变

结论及示意图

引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参!

//开辟了新的空间,包括保存字符串的常量池

 //此时 p 就不再指向 main中的p 了

P = new Person

解读 : P = null是在方法体中执行,所以只是把方法体里的p置空, 不会影响到main中的p

在看一个案例,下面的方法会对原来的对象有影响吗?

p=null 和 p = new

形参为对象

方法递归调用

简单的说: 递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂问题,同时可以让代码变得简洁。

例子

阶乘问题

//factorial 阶乘

public int factorial(int n) {

    if (n == 1) {

        return 1;

    } else {

        return factorial(n - 1) * n;

    }

}

打印问题

猴子吃桃问题        /chaper07/RecursionExercise01.java

    猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!

        以后每天猴子都吃其中的一半,然后再多吃一个。当到第 10 天时,

        想再吃时(即还没吃),发现只有 1 个桃子了。问题:最初共多少个桃子?

递归重要规则

  1. 执行一个方法是,就创建一个新的受保护和独立空间(栈空间)。
  2. 方法的局部百年来是独立的,不会互相影响,比如上面阶乘中的n变量。
  3. 如果方阿飞中使用的是引用类型变量(如数组、对象),就会共享该引用类型的数据。
  4. 递归必须向退出递归的条件逼近,否则就是无限递归,(出现StackOverflowError,死龟了).
  5. 当一个方法执行完毕,或者遇到return, 就会返回,遵守谁调用,就将结果返回给谁, 同时当方法执行完毕或者返回时,该方法也就执行完毕.

方法重载

基本介绍

java 中允许同一个类中,多个同名方法的存在,但要求 形参列表不一致

重载的好处

1) 减轻了起名的麻烦

2) 减轻了记名的麻烦

重载注意事项和使用细节

  1. 方法名:必须相同
  2. 形参列表:必须不同(形参类型 或 个数 或 顺序,至少有一样不同,参数名无要求)
  3. 返回类型:无要求
  4. 修饰符: 无要求

重载细节:

//传参: 实参 -> 形参 可以发生自动类型转换

    // int -> double

    System.out.println(s.max(10.3, 4.3,20));

但是反过来不可以

在匹配时,  优先匹配参数类型相同的(不用自动转换)

如:

    public double max(double a, double b, double c)

    public double max(double a, double b, int c)

可变参数

基本概念

java 允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。就可以通过可变参数实现。

基本语法

访问修饰符 返回类型 方法名(数据类型... 形参名) {            }

注意事项和使用细节

  1. 可变参数的实参可以为0个或任意多个。
  2. 可变参数的实参可以为数组。
  3. 可变参数的本质就是数组。
  4. 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数放在最后
  5. 一个形参列表中只能出现一个可变参数。

作用域

基本使用

面向对象中,变量作用域是非常重要知识点,相对来说不是特别好理解,请大家注

意听,认真思考,要求深刻掌握变量作用域。VarScope.java

1.在java编程中, 主要的变量就是属性(成员变量)和局部变量。

2.我们说的局部变量一般是指在成员方法中定义的变量。 [举例Cat类: cry]

3. java中作用域的分类

全局变量:也就是属性,作用域为整个类体Cat类: cry eat等方法使用属性

[举例]

局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中!

4.全局变量(属性)可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。[举例]

作用域使用细节和注意事项()

  1. 属性和局部变量可以重名,访问时遵循就近原则。(或使用this 准确调用属性)
  1. 在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名。[举例]
  2. 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁。即在一次方法调用过程中。
  3. 作用域范围不同

    全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)

    局部变量:只能在本类中对应的方法中使用

  1. 修饰符不同

    全局变量/属性可以加修饰符, 局部变量不可以加修饰符

构造方法/构造器

基本语法

[修饰符] 方法名(形参列表){

方法体;

}

 老韩说明:

1) 构造器的修饰符可以默认, 也可以是 public protected private

2) 构造器没有返回值

3) 方法名 和类名字必须一样

4) 参数列表 和 成员方法一样的规则

5) 构造器的调用, 由系统完成

基本介绍

构造方法又叫构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:

1) 方法名和类名相同

2) 没有返回值

3) 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化。

构造器使用细节和注意事项

ConstructorDetail.java

1.一个类可以定义多个不同的构造器,即构造器重载

比如:我们可以再给Person类定义一个构造器,用来创建对象的时候,只指定人名,不需要指定年龄

2.构造器名和类名要相同3.构造器没有返回值

4.构造器是完成对象的初始化,并不是创建对象

5.在创建对象时,系统自动的调用该类的构造方法

6.如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也

叫默认构造器),比如 Dog 00,使用javap指令反编译看看

7.一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无

参构造器,除非显式的定义一下,即:Dog(){  } 写(这点很重要)

8. 构造器复用: 在一个构造器中调用另外一个构造器.(注: 调用语句必须放在第一句, 故而只能调用一个构造器) 如

对象创建的流程分析(自己模拟画一遍)

this关键字

为了便于理解,可以认为每个对象创建过后都有一个隐藏的 this 指向它本身.

传统方法访问: 遵循就近原则
this访问: 直接访问属性
 

this 的注意事项和使用细节

ThisDetail.java

1) this 关键字可以用来访问本类的属性、方法、构造器

2) this 用于区分当前类的属性和局部变量

3) 访问成员方法的语法:this.方法名(参数列表);

4) 访问构造器语法:this(参数列表); 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器, 必须放在第一条语句)

5) this 不能在类定义的外部使用,只能在类定义的方法中使用。

匿名对象

匿名对象

//老韩解读

        // 1. new Homework08() 是匿名对象, 匿名对象使用后,就不能再使用了(因为没有指向他所以被销毁)

        // 2. new Homework08().count1()  创建好匿名对象后,就调用count1

        new Homework08().count1(); //  10

        Homework08 t1 = new Homework08();

        t1.count2();  // 9

        t1.count2();  //10

八、面向对象编程(中级部分)

IDEA(集成开发环境)

模板/自定义模板

包的三大作用

  1. 区分相同名字的类。
  2. 当类很多时,可以很好的管理类【看java API 文档】
  3. 控制访问范围

包基本语法

包的本质分析(原理)

7常用的包

一个包下,包含很多的类,java 中常用的包有:

1) java.lang.* //lang 包是基本包,默认引入,不需要再引入. 2) java.util.* //util 包,系统提供的工具包, 工具类,使用 Scanner

3) java.net.* //网络包,网络开发

4) java.awt.* //是做 java 的界面开发,GUI

如何引入包

建议用那个类就引入哪个类。

包的注意事项和细节

PkgDetail.java

1. package的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一句package

2. import指令位置放在package的下面,在类定义前面,可以有多句且没有顺序要求。

访问修饰符

基本介绍

java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):

  1. 公开级别:用 public 修饰,对外公开
  2. 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
  3. 默认级别:没有修饰符号,向同一个包的类公开.
  4. 私有级别:用 private 修饰,只有类本身可以访问,不对外公开.

四种访问修饰符的访问范围和注意事项( 重要 背下来)

●使用的注意事项

1)修饰符可以用来修饰类中的属性,成员方法以及类

2)只有默认的和public才能修饰类!,并且遵循上述访问权限的特点。

3)因为没有学习继承,因此关于在子类中的访问权限,我们讲完子类后,在回头讲解

4)成员方法的访问规则和属性完全一样.

/com.hspedu.modifier :

细节:

如果父类有 默认 修饰的属性, 按下图来说在子类中是无权限访问的,但如果此父类和子类在一个包内,子类依然可以直接访问父类的 默认属性

面向对象编程-封装

基本介绍

封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。

封装的理解和好处

1)隐藏实现细节:方法(连接数据库)<--调用(传入参数..

2)可以对数据进行验证,保证安全合理

Person {name, age}

Person p = new Person);p.name = "jack" ;

p.age = 1200;//明显不合理

封装的实现步骤(三步)

1)将属性进行私有化private【不能直接修改属性】

2)提供一个公共的(public)set方法,用于对属性判断并赋值

public void setXxx(类型参数名)//Xxx表示某个属性

1/加入数据验证的业务逻辑

属性=参数名;

}

3)提供一个公共的(public)get方法,用于获取属性的值public 数据类型getXxx(){//权限判断,Xxx某个属性

return xx;

}

将构造器和 setXxx 结合

public Person(String name, int age, double salary) {

        // 直接使用构造器,会使数据校验失效

//        this.name = name;

//        this.age = age;

//        this.salary = salary;

        //应该在构造器中调用set 方法, 数据校验继续生效

        setName(name);

        setAge(age);

        setSalary(salary);

}

面向对象编程-继承(extends)

为什么需要继承

继承基本介绍和示意图

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中

抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。画出继承的示意图

Extends 关键字不能去掉

继承的基本语法

继承给编程带来的便利

1) 代码的复用性提高了

2) 代码的扩展性和维护性提高了

继承的深入讨论/细节问题(重要)

1) 子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

2) 子类必须调用父类的构造器, 完成父类的初始化

3) 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过(怎么理解。) [举例说明]

4) 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

5) super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

6) super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7) java 所有类都是 Object 类的子类, Object 是所有类的基类.

8) 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)

9) 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。

思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】

10) 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

可以说他两个可以抽象出共同特征, 如: 小狗是动物, 小学生是人

继承的本质讨论 / 子类创建的内存布局(重要)

继承的本质就是建立一个  查找关系

//?-> 这时请大家注意,要按照查找关系来返回信息

//(1) 首先看子类是否有该属性

//(2) 如果子类有这个属性,并且可以访问,则返回信息

//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)

//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...

细节

如果father 类中有 private int age;  gradePa类有 public int age;

//调用本类中的没有的属性,会严格按照查找关系来返回信息

        //比如此例:调用age时,首先看本类里没有->找父类里的age : 无访问权限

//        之后就是GrandPa类中有 public int age 也不会在往上找了,会直接在父类那儿报错

        System.out.println(son.age);

报错信息

'age' has private access in 'com.hspedu.extend_.Father'

子类创建的内存布局

 查找属性和方法:都是按照加载类信息顺序相反的方向找的

 super除了第一步直接从父类里面查找,其余逻辑一样

super关键字

基本介绍

super 代表父类的引用,用于访问父类的属性、方法、构造器。

基本语法     package com.hspedu.super_ super01

1.访问父类的属性,但不能访问父类的private属性[案例]

super.属性名;

2.访问父类的方法,不能访问父类的private方法

super.方法名(参数列表);

3.访问父类的构造器(这点前面用过):

super(参数列表);只能放在构造器的第一句,只能出现一句!

细节

//super 的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用 super 去访问爷爷类的成员; // 如果多个基类(上级类)中都有同名的成员,使用 super 访问遵循就近原则。A->B->C

//找 cal 方法时(cal() 和 this.cal()),顺序是:

// (1)先找本类,如果有,则调用

// (2)如果没有,则找父类(如果有,并可以调用,则调用)

// (3)如果父类没有,则继续找父类的父类,整个规则,就是一样的,直到 Object 类

// 提示:如果查找方法的过程中,找到了,但是不能访问, 则报错, cannot access

// 如果查找方法的过程中,没有找到,则提示方法不存在

cal() 等价于 this.cal()

//super.cal() 的顺序是直接查找父类,其他的规则一样

//super.cal()

访问属性时规则亦相同

super 给编程带来的便利/细节

/SuperDetail.java

1.调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)

2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果![举例]

3. super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中都有同名的成员,使用super 访问时遵循就近原则。A -> B -> C,当然也需要遵守访问权限的相关规则。

Super和 this 的比较

方法重写/覆盖(override)

基本介绍

简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法。

参见:

package com.hspedu.override_  Animal.java  Dog.java

注意事项和使用细节

方法重写也叫方法覆盖,需要满足下面的条件

方法重载与方法重写 比较

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值