2022年1月9日开始 1-2章 2022年1月17日完毕
程序:计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合。
特性
学习方法
dos 命令
本章作业
1. JDK = JRE + java开发工具
2. JRE = JVM + 核心类库
//环境变量path配置及其作用
1. 环境变量的作用是为了在dos的任意目录,可以去使用java 和 javac命令
2. 先配置 JAVA_HOME = 指向jdk安装的主目录
3. 编辑path环境变量,增加 %JAVA_HOME%\bin
//Java编写步骤
1. 编写java的源代码
2. javac 编译 ,得到对应的 .class 字节码文件
3. java 运行, 本质就是把 .class 加载到jvm 运行
//Java编写7个规范
1. 类,方法的注释,使用javadoc的方式,即文档注释
2. 非javadoc注释,往往是对代码的说明(给程序的维护者),说明如何修改,注意事项
3. 使用tab ,整体将代码右移, 使用 shift+tab 整体左移
4. 运算符和 = 的两边,给空格,代码看上去清楚 int n = 1 + 4;
5. 源码文件使用 utf-8编码
6. 行宽字符不要超过 80
7. 代码编程风格有两种 次行风格,行尾风格(推荐)
//初学者java易犯错误
1. 编译或者运行时,找不到文件 javac Hell0.java, 把文件名或者目录找对
2. 主类名和文件名不一致 , 修改时保持一致即可
3. 缺少;
4. 拼写错误,比如 1 -> l 0->0, void -> viod , 要求写代码时,一定要小心
强调: 先思考->自己练习->看老师评讲
3章-4章 2022年1月17日 2022年1月18日
变量
变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房 间,而通过变量名可以访问到变量(值)。
数据类型
public class CharDetail {
//编写一个main方法
public static void main(String[] args) {
//在java中,char的本质是一个整数,在默认输出时,是unicode码对应的字符
//要输出对应的数字,可以(int)字符
char c1 = 97;
System.out.println(c1); // a
char c2 = 'a'; //输出'a' 对应的 数字
System.out.println((int)c2);
char c3 = '韩';
System.out.println((int)c3);//38889
char c4 = 38889;
System.out.println(c4);//韩
//char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码.
System.out.println('a' + 10);//107
//课堂小测试
char c5 = 'b' + 1;//98+1==> 99
System.out.println((int)c5); //99
System.out.println(c5); //99->对应的字符->编码表ASCII(规定好的)=>c
}
}
类型转换
运算符 4章
5章 2022年1月18日 -2022年1月20日
流程控制
分支
switch
for循环
多重循环
// 打印九九乘法表
for(int i=1; i <= 9; i++){
for(int j=1;j <= i;j++){
System.out.print(j+"x"+i+"="+i*j+"\t");
}
System.out.println();
}
2. 打印半个金字塔
* //第 1 层 有 1 个*
** //第 2 层 有 2 个*
*** //第 3 层 有 3 个*
**** //第 4 层 有 4 个*
***** //第 5 层 有 5 个*
3. 打印整个金字塔
* //第 1 层 有 1 个* 2 * 1 -1 有 4=(总层数-1)个空格
*** //第 2 层 有 3 个* 2 * 2 -1 有 3=(总层数-2)个空格
***** //第 3 层 有 5 个* 2 * 3 -1 有 2=(总层数-3)个空格
******* //第 4 层 有 7 个* 2 * 4 -1 有 1=(总层数-4)个空格
********* //第 5 层 有 9 个* 2 * 5 -1 有 0=(总层数-5)个空格
4. 打印空心的金字塔 [最难的]
* //第 1 层 有 1 个* 当前行的第一个位置是*,最后一个位置也是*
* * //第 2 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
* * //第 3 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
* * //第 4 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
********* //第 5 层 有 9 个* 全部输出*
先死后活
韩顺平循序渐进学 Java 零基础
第 132页
5 层数做成变量 int totalLevel = 5;
//小伙伴 技术到位,就可以很快的把代码写出
*/
int totalLevel = 20; //层数
for(int i = 1; i <= totalLevel; i++) { //i 表示层数
//在输出*之前,还有输出 对应空格 = 总层数-当前层
for(int k = 1; k <= totalLevel - i; k++ ) {
System.out.print(" ");
}
//控制打印每层的*个数
for(int j = 1;j <= 2 * i - 1;j++) {
//当前行的第一个位置是*,最后一个位置也是*, 最后一层全部 *
if(j == 1 || j == 2 * i - 1 || i == totalLevel) {
System.out.print("*");
} else { //其他情况输出空格
System.out.print(" ");
}
}
//每打印完一层的*后,就换行 println 本身会换行
System.out.println("");
}
}
}
https://www.bilibili.com/video/BV1fh411y7R8?p=137&spm_id_from=pageDriver
break
continue
return
本章练习:
public class Main
{
public static void main (String[] args)
{
System.out.println("this is java test");
double cash = 100000; //现金
int time=0; // 次数
while(cash>=1000){
if(cash > 50000){
cash = cash * (1-0.05);
time++;
}
if(cash <= 50000){
cash = cash - 1000;
time++;
}
if(cash<0){
break;
}
}
System.out.println(time);
}
}
public class Homework01 {
//编写一个main方法
public static void main(String[] args) {
/*
某人有100,000元,每经过一次路口,需要交费,规则如下:
1) 当现金>50000时,每次交5%
2) 当现金<=50000时,每次交1000
编程计算该人可以经过多少次路口, 要求: 使用 while + break方式完成
思路分析
1. 定义 double money 保存 100000
2. 根据题的要求,我们分析出来有三种情况
money > 50000
money >=1000 && money <= 50000
money < 1000
3. 使用多分支 if-elseif-else
4. while+break[money < 1000], 同时使用一个变量count来保存通过路口
代码实现
*/
double money = 100000;//还有多少钱
int count = 0; //累积过的路口
while(true) { //无限循环
if(money > 50000) { //过路口
//money = money - money * 0.05;
money *= 0.95; //过了这个路口后,还有这么多钱
count++;
} else if(money >=1000) {
money -= 1000;
count++;
} else { //钱不够1000
break;
}
}
System.out.println("100000 可以过 " + count + " 路口..");
}
}
本章练习2:
public class Main
{
public static void main (String[] args)
{
System.out.println("this is java test");
//定义一个三位数
int num = 133;
//取出百位
int baiwei = num/100;
int shiwei = num/10%10;
int gewei = num%10;
// 利用if进行判断
if(num==baiwei*baiwei*baiwei+shiwei*shiwei*shiwei+gewei*gewei*gewei){
System.out.println("是水仙花数");
}else{
System.out.println("不是水仙花数");
}
}
}
public class Homework06 {
//编写一个main方法
public static void main(String[] args) {
/*
输出1-100之间的不能被5整除的数,每5个一行
思路分析
1. 先输出1-100的所有数
2. 然后过滤输出 不能被5整除的数 i % 5 !=0
3. 每5个一行, 我们使用 int count 统计输出的个数 当 count%5=0就说明
输出了5个,这时,我们输出 一个换行即可控制
代码实现
*/
int count = 0; //统计输出的个数
for(int i = 1; i <= 100; i++) {
if(i % 5 != 0) {
count++;
System.out.print(i + "\t");
//判断, 每满5个,就输出一个换行..
if(count % 5 == 0) {
System.out.println();
}
}
}
}
}
public static void main (String[] args)
{
char a = ' ';
for (int i = 65; i< 65+26; i++){
a = (char)i;
System.out.println(a);
}
for (int i = 97; i< 97+26; i++){
a = (char)i;
System.out.println(a);
}
}
public class Homework07 {
//编写一个main方法
public static void main(String[] args) {
//输出小写的a-z以及大写的Z-A
//考察我们对 a-z编码和 for的综合使用
//思路分析
//1. 'b' = 'a' + 1 c = 'a' + 2
//2. 使用for搞定
for(char c1 = 'a'; c1 <= 'z'; c1++) {
System.out.print(c1 +" ");
}
System.out.println("============");
//灵活的使用,编程..
for(char c1 = 'Z'; c1 >= 'A'; c1--) {
System.out.print(c1 +" ");
}
}
}
public class Main
{
public static void main (String[] args)
{
double sum = 0;
for(double i = 1; i <= 100; i++){
if (i%2!=0){
sum = sum + 1/i;
}else{
sum = sum - 1/i;
}
}
System.out.println(sum);
}
}
public class Homework08 {
//编写一个main方法
public static void main(String[] args) {
/*
求出1-1/2+1/3-1/4…..1/100的和
思路分析
1. 1-1/2+1/3-1/4…..1/100 = (1/1)-(1/2)+(1/3)-(1/4)...1/100
2. 从上面的分析我们可以看到
(1) 一共有100数 , 分子为1 , 分母从1-100
(2) 还发现 当分母为奇数时,前面是 +, 当分母是偶数时,前面是-
3. 我们可以使用 for + 判断即可完成
4. 把结果存放到 double sum
5. 这里有一个隐藏的陷阱,要把 公式分子 1 写出1.0 才能得到精确的小数
*/
double sum = 0;
for(int i = 1; i <= 100; i++) {
//判断是奇数还是偶数,然后做不同的处理
if( i % 2 != 0) {//分母为奇数
sum += 1.0/i;
} else { //分母我偶数
sum -= 1.0/i;
}
}
System.out.println("sum=" + sum);
}
}
public class Main
{
public static void main (String[] args)
{
int sum = 0;
int total = 0;
for (int i = 1; i <= 100 ; i++){
for(int j = 1; j <= i; j++){
sum = sum + j;
}
}
System.out.println(sum);
}
}
6章 2022年1月20日-2022年1月21日
数组
案例1:
import java.util.Scanner;
public class Main
{
public static void main (String[] args)
{
char[] array = new char[26];
for (int i = 0; i < array.length ; i++ ){
array[i] = (char)(i+'A');
System.out.println(array);
}
}
}
public class ArrayExercise01 {
//编写一个main方法
public static void main(String[] args) {
/*
创建一个char类型的26个元素的数组,分别 放置'A'-'Z'。
使用for循环访问所有元素并打印出来。
提示:char类型数据运算 'A'+1 -> 'B'
思路分析
1. 定义一个 数组 char[] chars = new char[26]
2. 因为 'A' + 1 = 'B' 类推,所以老师使用for来赋值
3. 使用for循环访问所有元素
*/
char[] chars = new char[26];
for( int i = 0; i < chars.length; i++) {//循环26次
//chars 是 char[]
//chars[i] 是 char
chars[i] = (char)('A' + i); //'A' + i 是int , 需要强制转换
}
//循环输出
System.out.println("===chars数组===");
for( int i = 0; i < chars.length; i++) {//循环26次
System.out.print(chars[i] + " ");
}
}
}
案例2:
public class Main
{
public static void main (String[] args)
{
int[] arr = {4,-1,9,10,23};
int max = arr[0];
int maxIndex = 0;
for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历arr
if(max < arr[i]){
max = arr[i];
maxIndex = i;
}
}
System.out.println("max=" + max + " maxIndex=" + maxIndex);
}
}
public class ArrayExercise02 {
//编写一个main方法
public static void main(String[] args) {
//请求出一个数组int[]的最大值 {4,-1,9, 10,23},并得到对应的下标
//老韩思路分析
//1. 定义一个int数组 int[] arr = {4,-1,9, 10,23};
//2. 假定 max = arr[0] 是最大值 , maxIndex=0;
//3. 从下标 1 开始遍历arr, 如果max < 当前元素,说明max 不是真正的
// 最大值, 我们就 max=当前元素; maxIndex=当前元素下标
//4. 当我们遍历这个数组arr后 , max就是真正的最大值,maxIndex最大值
// 对应的下标
int[] arr = {4,-1,9,10,23};
int max = arr[0];//假定第一个元素就是最大值
int maxIndex = 0; //
for(int i = 1; i < arr.length; i++) {//从下标 1 开始遍历arr
if(max < arr[i]) {//如果max < 当前元素
max = arr[i]; //把max 设置成 当前元素
maxIndex = i;
}
}
//当我们遍历这个数组arr后 , max就是真正的最大值,maxIndex最大值下标
System.out.println("max=" + max + " maxIndex=" + maxIndex);
}
}
数组赋值机制
public class ArrayAssign {
//编写一个main方法
public static void main(String[] args) {
//基本数据类型赋值, 赋值方式为值拷贝
//n2的变化,不会影响到n1的值
int n1 = 10;
int n2 = n1;
n2 = 80;
System.out.println("n1=" + n1);//10
System.out.println("n2=" + n2);//80
//数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用赋值
//是一个地址 , arr2变化会影响到 arr1
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;//把 arr1赋给 arr2
arr2[0] = 10;
//看看arr1的值
System.out.println("====arr1的元素====");
for(int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);//10, 2, 3
}
System.out.println("====arr2的元素====");
for(int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);//10, 2, 3
}
}
}
数组翻转
数组扩容
public class ArrayAdd {
//编写一个main方法
public static void main(String[] args) {
/*
要求:实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java
1.原始数组使用静态分配 int[] arr = {1,2,3}
2.增加的元素4,直接放在数组的最后 arr = {1,2,3,4}
3.用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
思路分析
1. 定义初始数组 int[] arr = {1,2,3}//下标0-2
2. 定义一个新的数组 int[] arrNew = new int[arr.length+1];
3. 遍历 arr 数组,依次将arr的元素拷贝到 arrNew数组
4. 将 4 赋给 arrNew[arrNew.length - 1] = 4;把4赋给arrNew最后一个元素
5. 让 arr 指向 arrNew ; arr = arrNew; 那么 原来arr数组就被销毁
*/
int[] arr = {1,2,3};
int[] arrNew = new int[arr.length + 1];
//遍历 arr 数组,依次将arr的元素拷贝到 arrNew数组
for(int i = 0; i < arr.length; i++) {
arrNew[i] = arr[i];
}
//把4赋给arrNew最后一个元素
arrNew[arrNew.length - 1] = 4;
//让 arr 指向 arrNew,
arr = arrNew;
//输出arr 看看效果
System.out.println("====arr扩容后元素情况====");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
排序
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class Main
{
public static void main (String[] args)
{
int[] arr = new int[80];
for(int i =0; i < 80;i++) {
arr[i] = (int)(Math.random() * 80); //生成一个[0, 8000000) 数
}
//测试冒泡排序
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
// 将前面额冒泡排序算法,封装成一个方法
public static void bubbleSort(int[] arr){
int temp = 0;
boolean flag = false;
for(int i = 0; i < arr.length - 1; i++){
for(int j = 0; j < arr.length - 1 - i;j++){
if(arr[j] > arr[j+1]){
flag = true;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
if(!flag){
break;
}else{
flag = false;
}
}
}
}
查找
import java.util.Scanner;
public class SeqSearch {
//编写一个main方法
public static void main(String[] args) {
/*
有一个数列:白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王猜数游戏:
从键盘中任意输入一个名称,判断数列中是否包含此名称【顺序查找】
要求: 如果找到了,就提示找到,并给出下标值
思路分析
1. 定义一个字符串数组
2. 接收用户输入, 遍历数组,逐一比较,如果有,则提示信息,并退出
*/
//定义一个字符串数组
String[] names = {"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"};
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入名字");
String findName = myScanner.next();
//遍历数组,逐一比较,如果有,则提示信息,并退出
//这里老师给大家一个编程思想/技巧, 一个经典的方法
int index = -1;
for(int i = 0; i < names.length; i++) {
//比较 字符串比较 equals, 如果要找到名字就是当前元素
if(findName.equals(names[i])) {
System.out.println("恭喜你找到 " + findName);
System.out.println("下标为= " + i);
//把i 保存到 index
index = i;
break;//退出
}
}
if(index == -1) { //没有找到
System.out.println("sorry ,没有找到 " + findName);
}
}
}
二维数组
public class TwoDimensionalArray01 {
//编写一个main方法
public static void main(String[] args) {
/*
请用二维数组输出如下图形
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0
*/
//什么是二维数组:
//老韩解读
//1. 从定义形式上看 int[][]
//2. 可以这样理解,原来的一维数组的每个元素是一维数组, 就构成二维数组
int[][] arr = { {0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0},
{0,2, 0, 3, 0, 0},
{0, 0, 0, 0, 0, 0} };
//关于二维数组的关键概念
//(1)
System.out.println("二维数组的元素个数=" + arr.length);
//(2) 二维数组的每个元素是一维数组, 所以如果需要得到每个一维数组的值
// 还需要再次遍历
//(3) 如果我们要访问第 (i+1)个一维数组的第j+1个值 arr[i][j];
// 举例 访问 3, =》 他是第3个一维数组的第4个值 arr[2][3]
System.out.println("第3个一维数组的第4个值=" + arr[2][3]); //3
//输出二维图形
for(int i = 0; i < arr.length; i++) {//遍历二维数组的每个元素
//遍历二维数组的每个元素(数组)
//老韩解读
//1. arr[i] 表示 二维数组的第i+1个元素 比如arr[0]:二维数组的第一个元素
//2. arr[i].length 得到 对应的 每个一维数组的长度
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " "); //输出了一维数组
}
System.out.println();//换行
}
}
}
杨辉三角
public class YangHui {
//编写一个main方法
public static void main(String[] args) {
/*
使用二维数组打印一个 10 行杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
规律
1.第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素的值. arr[i][j]
arr[i][j] = arr[i-1][j] + arr[i-1][j-1]; //必须找到这个规律
*/
int[][] yangHui = new int[12][];
for(int i = 0; i < yangHui.length; i++) {//遍历yangHui的每个元素
//给每个一维数组(行) 开空间
yangHui[i] = new int[i+1];
//给每个一维数组(行) 赋值
for(int j = 0; j < yangHui[i].length; j++){
//每一行的第一个元素和最后一个元素都是1
if(j == 0 || j == yangHui[i].length - 1) {
yangHui[i][j] = 1;
} else {//中间的元素
yangHui[i][j] = yangHui[i-1][j] + yangHui[i-1][j-1];
}
}
}
//输出杨辉三角
for(int i = 0; i < yangHui.length; i++) {
for(int j = 0; j < yangHui[i].length; j++) {//遍历输出该行
System.out.print(yangHui[i][j] + "\t");
}
System.out.println();//换行.
}
}
}
本章练习
本章作业3:
public class Homework04 {
//编写一个main方法
public static void main(String[] args) {
/*
已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序, 比如:
[10, 12, 45, 90], 添加23 后, 数组为 [10, 12,23, 45, 90]
思路 本质数组扩容 + 定位
1. 我们先确定 添加数应该插入到哪个索引
2. 然后扩容
*/
//先定义原数组
int[] arr = {10, 12, 45, 90};
int insertNum = 111;
int index = -1; //index就是要插入的位置
//遍历 arr数组, 如果发现 insertNum<=arr[i], 说明 i 就是要插入的位置
//使用 index 保留 index = i;
//如果遍历完后,没有发现 insertNum<=arr[i], 说明 index = arr.length
//即:添加到arr的最后
for(int i = 0; i < arr.length; i++) {
if(insertNum <= arr[i]) {
index = i;
break; //找到位置后,就退出
}
}
//判断index 的值
if(index == -1) { //说明没有还没有找到位置
index = arr.length;
}
//扩容
//先创建一个新的数组,大小 arr.length + 1
int[] arrNew = new int[arr.length + 1];
//下面老师准备将arr的元素拷贝到 arrNew ,并且要跳过 index位置
/*
分析:
int[] arr = {10, 12, 45, 90};
arrNew = { }
*/
//i 控制arrNew的下标 , j用来控制arr数组的下标
for(int i = 0, j = 0; i < arrNew.length; i++) {
if( i != index ) { //说明可以把 arr的元素拷贝到 arrNew
arrNew[i] = arr[j];
j++;
} else { //i这个位置就是要插入的数
arrNew[i] = insertNum;
}
}
//让arr 指向 arrNew , 原来的数组,就成为垃圾,被销毁
arr = arrNew;
System.out.println("======插入后,arr数组的元素情况======");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
本章作业4:
public class Homework05 {
//编写一个main方法
public static void main(String[] args) {
/*
随机生成10个整数(1_100的范围)保存到数组,
并倒序打印以及求平均值、求最大值和最大值的下标、
并查找里面是否有 8 Homework05.java
*/
int[] arr = new int[10];
//(int)(Math.random() * 100) + 1 生产 随机数 1-100
for(int i = 0; i < arr.length; i++) {
arr[i] = (int)(Math.random() * 100) + 1;
}
System.out.println("====arr的元素情况=====");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
System.out.println("\n====arr的元素情况(倒序)=====");
for(int i = arr.length -1; i >= 0; i--) {
System.out.print(arr[i] + "\t");
}
//平均值、求最大值和最大值的下标
//我们这里将需要一起完成
//
double sum = arr[0];
int max = arr[0];
int maxIndex = 0;
for(int i = 1; i < arr.length; i++ ) {
sum += arr[i]; //累积和
if( max < arr[i]) {//说明max不是最大值,就变化
max = arr[i];
maxIndex = i;
}
}
System.out.println("\nmax=" + max + " maxIndex=" + maxIndex);
System.out.println("\n平均值=" + (sum / arr.length));
//查找数组中是否有8->使用顺序查找
int findNum = 8;
int index = -1; //如果找到,就把下标记录到 index
for(int i = 0; i < arr.length; i++) {
if(findNum == arr[i]) {
System.out.println("找到数" + findNum + " 下标=" + i);
index = i;
break;
}
}
if(index == -1) {
System.out.println("没有找到数" + findNum );
}
}
}
public class Homework07 {
//编写一个main方法
public static void main(String[] args) {
//冒泡排序
//要求从小到大
int[] arr = {20, -1, 89, 2, 890, 7};
int temp = 0; //辅助交换
for(int i = 0; i < arr.length -1 ; i++) {//外层循环(轮)
for(int j = 0; j < arr.length - 1 - i; j++) {//每轮的比较次数
//如果是从小到大,条件是 arr[j] > arr[j+1]
//如果是从大到小,条件是 arr[j] < arr[j+1]
if(arr[j] > arr[j+1]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//搞定
System.out.println("\n==== 排序后====");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
7章 2022年1月21日 - 2022年1月22日
public class Object01 {
//编写一个main方法
public static void main(String[] args) {
/*
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。
还有一只叫小花,今年100岁,花色。请编写一个程序,当用户输入小猫的名字时,
就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,
则显示 张老太没有这只猫猫。
*/
//单独变量来解决 => 不利于数据的管理(你把一只猫的信息拆解)
//第1只猫信息
// String cat1Name = "小白";
// int cat1Age = 3;
// String cat1Color = "白色";
// //第2只猫信息
// String cat2Name = "小花";
// int cat2Age = 100;
// String cat2Color = "花色";
//数组 ===>(1)数据类型体现不出来(2) 只能通过[下标]获取信息,造成变量名字和内容
// 的对应关系不明确(3) 不能体现猫的行为
//第1只猫信息
// String[] cat1 = {"小白", "3", "白色"};
// String[] cat2 = {"小花", "100", "花色"};
//使用OOP面向对象解决
//实例化一只猫[创建一只猫对象]
//老韩解读
//1. new Cat() 创建一只猫(猫对象)
//2. Cat cat1 = new Cat(); 把创建的猫赋给 cat1
//3. cat1 就是一个对象
Cat cat1 = new Cat();
cat1.name = "小白";
cat1.age = 3;
cat1.color = "白色";
cat1.weight = 10;
//创建了第二只猫,并赋给 cat2
//cat2 也是一个对象(猫对象)
Cat cat2 = new Cat();
cat2.name = "小花";
cat2.age = 100;
cat2.color = "花色";
cat2.weight = 20;
//怎么访问对象的属性呢
System.out.println("第1只猫信息" + cat1.name
+ " " + cat1.age + " " + cat1.color + " " + cat1.weight);
System.out.println("第2只猫信息" + cat2.name
+ " " + cat2.age + " " + cat2.color + " " + cat2.weight);
}
}
//使用面向对象的方式来解决养猫问题
//
//定义一个猫类 Cat -> 自定义的数据类型
class Cat {
//属性/成员变量
String name; //名字
int age; //年龄
String color; //颜色
//double weight; //体重
//行为
}
快速入门
public class Object01 {
//编写一个main方法
public static void main(String[] args) {
/*
张老太养了两只猫猫:一只名字叫小白,今年3岁,白色。
还有一只叫小花,今年100岁,花色。请编写一个程序,当用户输入小猫的名字时,
就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,
则显示 张老太没有这只猫猫。
*/
//单独变量来解决 => 不利于数据的管理(你把一只猫的信息拆解)
//第1只猫信息
// String cat1Name = "小白";
// int cat1Age = 3;
// String cat1Color = "白色";
// //第2只猫信息
// String cat2Name = "小花";
// int cat2Age = 100;
// String cat2Color = "花色";
//数组 ===>(1)数据类型体现不出来(2) 只能通过[下标]获取信息,造成变量名字和内容
// 的对应关系不明确(3) 不能体现猫的行为
//第1只猫信息
// String[] cat1 = {"小白", "3", "白色"};
// String[] cat2 = {"小花", "100", "花色"};
//使用OOP面向对象解决
//实例化一只猫[创建一只猫对象]
//老韩解读
//1. new Cat() 创建一只猫(猫对象)
//2. Cat cat1 = new Cat(); 把创建的猫赋给 cat1
//3. cat1 就是一个对象
Cat cat1 = new Cat();
cat1.name = "小白";
cat1.age = 3;
cat1.color = "白色";
cat1.weight = 10;
//创建了第二只猫,并赋给 cat2
//cat2 也是一个对象(猫对象)
Cat cat2 = new Cat();
cat2.name = "小花";
cat2.age = 100;
cat2.color = "花色";
cat2.weight = 20;
//怎么访问对象的属性呢
System.out.println("第1只猫信息" + cat1.name
+ " " + cat1.age + " " + cat1.color + " " + cat1.weight);
System.out.println("第2只猫信息" + cat2.name
+ " " + cat2.age + " " + cat2.color + " " + cat2.weight);
}
}
//使用面向对象的方式来解决养猫问题
//
//定义一个猫类 Cat -> 自定义的数据类型
class Cat {
//属性/成员变量
String name; //名字
int age; //年龄
String color; //颜色
//double weight; //体重
//行为
}
public class PropertiesDetail {
//编写一个main方法
public static void main(String[] args) {
//创建Person对象
//p1 是对象名(对象引用)
//new Person() 创建的对象空间(数据) 才是真正的对象
Person p1 = new Person();
//对象的属性默认值,遵守数组规则:
//int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000,boolean false,String null
System.out.println("\n当前这个人的信息");
System.out.println("age=" + p1.age + " name="
+ p1.name + " sal=" + p1.sal + " isPass=" + p1.isPass) ;
}
}
class Person {
//四个属性
int age;
String name;
double sal;
boolean isPass;
}
成员方法
public class Method01 {
//编写一个main方法
public static void main(String[] args) {
//方法使用
//1. 方法写好后,如果不去调用(使用),不会输出
//2. 先创建对象 ,然后调用方法即可
Person p1 = new Person();
p1.speak(); //调用方法
p1.cal01(); //调用cal01方法
p1.cal02(5); //调用cal02方法,同时给n = 5
p1.cal02(10); //调用cal02方法,同时给n = 10
//调用getSum方法,同时num1=10, num2=20
//把 方法 getSum 返回的值,赋给 变量 returnRes
int returnRes = p1.getSum(10, 20);
System.out.println("getSum方法返回的值=" + returnRes);
}
}
class Person {
String name;
int age;
//方法(成员方法)
//添加speak 成员方法,输出 “我是一个好人”
//老韩解读
//1. public 表示方法是公开
//2. void : 表示方法没有返回值
//3. speak() : speak是方法名, () 形参列表
//4. {} 方法体,可以写我们要执行的代码
//5. System.out.println("我是一个好人"); 表示我们的方法就是输出一句话
public void speak() {
System.out.println("我是一个好人");
}
//添加cal01 成员方法,可以计算从 1+..+1000的结果
public void cal01() {
//循环完成
int res = 0;
for(int i = 1; i <= 1000; i++) {
res += i;
}
System.out.println("cal01方法 计算结果=" + res);
}
//添加cal02 成员方法,该方法可以接收一个数n,计算从 1+..+n 的结果
//老韩解读
//1. (int n) 形参列表, 表示当前有一个形参 n, 可以接收用户输入
public void cal02(int n) {
//循环完成
int res = 0;
for(int i = 1; i <= n; i++) {
res += i;
}
System.out.println("cal02方法 计算结果=" + res);
}
//添加getSum成员方法,可以计算两个数的和
//老韩解读
//1. public 表示方法是公开的
//2. int :表示方法执行后,返回一个 int 值
//3. getSum 方法名
//4. (int num1, int num2) 形参列表,2个形参,可以接收用户传入的两个数
//5. return res; 表示把 res 的值, 返回
public int getSum(int num1, int num2) {
int res = num1 + num2;
return res;
}
}
方法的妙用
public class Method02 {
//编写一个main方法
public static void main(String[] args) {
//请遍历一个数组 , 输出数组的各个元素值
int [][] map = {{0,0,1},{1,1,1},{1,1,3}};
//使用方法完成输出, 创建MyTools对象
MyTools tool = new MyTools();
//遍历map数组
//传统的解决方式就是直接遍历
// for(int i = 0; i < map.length; i++) {
// for(int j = 0; j < map[i].length; j++) {
// System.out.print(map[i][j] + "\t");
// }
// System.out.println();
// }
//使用方法
tool.printArr(map);
//....
//
//要求再次遍历map数组
// for(int i = 0; i < map.length; i++) {
// for(int j = 0; j < map[i].length; j++) {
// System.out.print(map[i][j] + "\t");
// }
// System.out.println();
// }
tool.printArr(map);
//...再次遍历
//
// for(int i = 0; i < map.length; i++) {
// for(int j = 0; j < map[i].length; j++) {
// System.out.print(map[i][j] + "\t");
// }
// System.out.println();
// }
tool.printArr(map);
}
}
//把输出的功能,写到一个类的方法中,然后调用该方法即可
class MyTools {
//方法,接收一个二维数组
public void printArr(int[][] map) {
System.out.println("=======");
//对传入的map数组进行遍历输出
for(int i = 0; i < map.length; i++) {
for(int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + "_");
}
System.out.println();
}
}
}
public class MethodDetail {
public static void main(String[] args) {
AA a = new AA();
int[] res = a.getSumAndSub(1, 4);
System.out.println("和=" + res[0]);
System.out.println("差=" + res[1]);
//细节: 调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型 的参数
byte b1 = 1;
byte b2 = 2;
a.getSumAndSub(b1, b2);//byte -> int
//a.getSumAndSub(1.1, 1.8);//double ->int(×)
//细节: 实参和形参的类型要一致或兼容、个数、顺序必须一致
//a.getSumAndSub(100);//× 个数不一致
a.f3("tom", 10); //ok
//a.f3(100, "jack"); // 实际参数和形式参数顺序不对
}
}
class AA {
//细节: 方法不能嵌套定义
public void f4() {
//错误
// public void f5() {
// }
}
public void f3(String str, int n) {
}
//1. 一个方法最多有一个返回值 [思考,如何返回多个结果 返回数组 ]
public int[] getSumAndSub(int n1, int n2) {
int[] resArr = new int[2]; //
resArr[0] = n1 + n2;
resArr[1] = n1 - n2;
return resArr;
}
//2. 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
// 具体看 getSumAndSub
//
//3. 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值;
// 而且要求返回值类型必须和return的值类型一致或兼容
public double f1() {
double d1 = 1.1 * 3;
int n = 100;
return n; // int ->double
//return d1; //ok? double -> int
}
//如果方法是void,则方法体中可以没有return语句,或者 只写 return ;
//老韩提示:在实际工作中,我们的方法都是为了完成某个功能,所以方法名要有一定含义
//,最好是见名知意
public void f2() {
System.out.println("hello1");
System.out.println("hello1");
System.out.println("hello1");
int n = 10;
//return ;
}
}
形参列表
public class MethodDetail02 {
//编写一个main方法
public static void main(String[] args) {
A a = new A();
//a.sayOk();
a.m1();
}
}
class A {
//同一个类中的方法调用:直接调用即可
//
public void print(int n) {
System.out.println("print()方法被调用 n=" + n);
}
public void sayOk() { //sayOk调用 print(直接调用即可)
print(10);
System.out.println("继续执行sayOK()~~~");
}
//跨类中的方法A类调用B类方法:需要通过对象名调用
public void m1() {
//创建B对象, 然后在调用方法即可
System.out.println("m1() 方法被调用");
B b = new B();
b.hi();
System.out.println("m1() 继续执行:)");
}
}
class B {
public void hi() {
System.out.println("B类中的 hi()被执行");
}
}
小练习
public class MethodExercise01 {
//编写一个main方法
public static void main(String[] args) {
AA a = new AA();
// if(a.isOdd(2)) {//T , 这样的写法以后会看到很多
// System.out.println("是奇数");
// } else {
// System.out.println("是偶数");
// }
//
//
// 使用print方法
a.print(4, 4, '#');
}
}
//编写类AA ,有一个方法:判断一个数是奇数odd还是偶数, 返回boolean
class AA {
//思路
//1. 方法的返回类型 boolean
//2. 方法的名字 isOdd
//3. 方法的形参 (int num)
//4. 方法体 , 判断
public boolean isOdd(int num) {
// if(num % 2 != 0) {
// return true;
// } else {
// return false;
// }
//return num % 2 != 0 ? true; false;
//
return num % 2 != 0;
}
//根据行、列、字符打印 对应行数和列数的字符,
//比如:行:4,列:4,字符#,则打印相应的效果
/*
####
####
####
####
*/
//思路
//1. 方法的返回类型 void
//2. 方法的名字 print
//3. 方法的形参 (int row, int col, char c)
//4. 方法体 , 循环
public void print(int row, int col, char c) {
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {//输出每一行
System.out.print(c);
}
System.out.println(); //换行
}
}
}
public class MethodParameter02 {
//编写一个main方法
public static void main(String[] args) {
//测试
B b = new B();
// int[] arr = {1, 2, 3};
// b.test100(arr);//调用方法
// System.out.println(" main的 arr数组 ");
// //遍历数组
// for(int i = 0; i < arr.length; i++) {
// System.out.print(arr[i] + "\t");
// }
// System.out.println();
//测试
Person p = new Person();
p.name = "jack";
p.age = 10;
b.test200(p);
//测试题, 如果 test200 执行的是 p = null ,下面的结果是 10
//测试题, 如果 test200 执行的是 p = new Person();..., 下面输出的是10
System.out.println("main 的p.age=" + p.age);//10000
}
}
class Person {
String name;
int age;
}
class B {
public void test200(Person p) {
//p.age = 10000; //修改对象属性
//思考
p = new Person();
p.name = "tom";
p.age = 99;
//思考
//p = null;
}
//B类中编写一个方法test100,
//可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化
public void test100(int[] arr) {
arr[0] = 200;//修改元素
//遍历数组
System.out.println(" test100的 arr数组 ");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
System.out.println();
}
}
public class MethodExercise02 {
//编写一个main方法
public static void main(String[] args) {
Person p = new Person();
p.name = "milan";
p.age = 100;
//创建tools
MyTools tools = new MyTools();
Person p2 = tools.copyPerson(p);
//到此 p 和 p2是Person对象,但是是两个独立的对象,属性相同
System.out.println("p的属性 age=" + p.age + " 名字=" + p.name);
System.out.println("p2的属性 age=" + p2.age + " 名字=" + p2.name);
//这里老师提示: 可以同 对象比较看看是否为同一个对象
System.out.println(p == p2);//false
}
}
class Person {
String name;
int age;
}
class MyTools {
//编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象。克隆对象,
//注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同
//
//编写方法的思路
//1. 方法的返回类型 Person
//2. 方法的名字 copyPerson
//3. 方法的形参 (Person p)
//4. 方法体, 创建一个新对象,并复制属性,返回即可
public Person copyPerson(Person p) {
//创建一个新的对象
Person p2 = new Person();
p2.name = p.name; //把原来对象的名字赋给p2.name
p2.age = p.age; //把原来对象的年龄赋给p2.age
return p2;
}
}
递归
方法重载
public class OverLoad01 {
//编写一个main方法
public static void main(String[] args) {
// System.out.println(100);
// System.out.println("hello,world");
// System.out.println('h');
// System.out.println(1.1);
// System.out.println(true);
//
MyCalculator mc = new MyCalculator();
System.out.println(mc.calculate(1, 2));
System.out.println(mc.calculate(1.1, 2));
System.out.println(mc.calculate(1, 2.1));
}
}
class MyCalculator {
//下面的四个 calculate方法构成了重载
//两个整数的和
public int calculate(int n1, int n2) {
System.out.println("calculate(int n1, int n2) 被调用");
return n1 + n2;
}
//没有构成方法重载, 仍然是错误的,因为是方法的重复定义
// public void calculate(int n1, int n2) {
// System.out.println("calculate(int n1, int n2) 被调用");
// int res = n1 + n2;
// }
//看看下面是否构成重载, 没有构成,而是方法的重复定义,就错了
// public int calculate(int a1, int a2) {
// System.out.println("calculate(int n1, int n2) 被调用");
// return a1 + a2;
// }
//一个整数,一个double的和
public double calculate(int n1, double n2) {
return n1 + n2;
}
//一个double ,一个Int和
public double calculate(double n1, int n2) {
System.out.println("calculate(double n1, int n2) 被调用..");
return n1 + n2;
}
//三个int的和
public int calculate(int n1, int n2,int n3) {
return n1 + n2 + n2;
}
}
练习
public class OverLoadExercise {
//编写一个main方法
public static void main(String[] args) {
//在主类的main ()方法中分别用参数区别调用三个方法
Methods method = new Methods();
method.m(10);//100
method.m(10, 20);//200
method.m("韩顺平教育 hello");//字符串信息
//测试
System.out.println(method.max(10, 24)); // 24
System.out.println(method.max(10.0, 21.4)); // 21.4
System.out.println(method.max(10.0, 1.4, 30.0)); // 30.0
}
}
/*
编写程序,类Methods中定义三个重载方法并调用。方法名为m。
三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别执行平方运算并输出结果,
相乘并输出结果,输出字符串信息。在主类的main ()方法中分别用参数区别调用三个方法
定义三个重载方法max(),第一个方法,返回两个int值中的最大值,
第二个方法,返回两个double值中的最大值,第三个方法,
返回三个double值中的最大值,并分别调用三个方法
*/
class Methods {
//分析
//1 方法名 max
//2 形参 (int,int)
//3.int
public int max(int n1, int n2) {
return n1 > n2 ? n1 : n2;
}
//分析
//1 方法名 max
//2 形参 (double,double)
//3.double
public double max(double n1, double n2) {
return n1 > n2 ? n1 : n2;
}
//分析
//1 方法名 max
//2 形参 (double,double,double)
//3.double
public double max(double n1, double n2, double n3) {
System.out.println("max(double n1, double n2, double n3)");
//求出n1 和 n2的最大值
double max1 = n1 > n2 ? n1 : n2;
return max1 > n3 ? max1 : n3;
}
public double max(double n1, double n2, int n3) {
System.out.println("max(double n1, double n2, int n3)");
//求出n1 和 n2的最大值
double max1 = n1 > n2 ? n1 : n2;
return max1 > n3 ? max1 : n3;
}
//分析
//1 方法名 m
//2 形参 (int)
//3.void
public void m(int n) {
System.out.println("平方=" + (n * n));
}
//1 方法名 m
//2 形参 (int, int)
//3.void
public void m(int n1, int n2) {
System.out.println("相乘=" + (n1 * n2));
}
//1 方法名 m
//2 形参 (String)
//3.void
public void m(String str) {
System.out.println("传入的str=" + str);
}
}
可变参数
public class VarParameter01 {
//编写一个main方法
public static void main(String[] args) {
HspMethod m = new HspMethod();
System.out.println(m.sum(1, 5, 100)); //106
System.out.println(m.sum(1,19)); //20
}
}
class HspMethod {
//可以计算 2个数的和,3个数的和 , 4. 5, 。。
//可以使用方法重载
// public int sum(int n1, int n2) {//2个数的和
// return n1 + n2;
// }
// public int sum(int n1, int n2, int n3) {//3个数的和
// return n1 + n2 + n3;
// }
// public int sum(int n1, int n2, int n3, int n4) {//4个数的和
// return n1 + n2 + n3 + n4;
// }
//.....
//上面的三个方法名称相同,功能相同, 参数个数不同-> 使用可变参数优化
//老韩解读
//1. int... 表示接受的是可变参数,类型是int ,即可以接收多个int(0-多)
//2. 使用可变参数时,可以当做数组来使用 即 nums 可以当做数组
//3. 遍历 nums 求和即可
public int sum(int... nums) {
//System.out.println("接收的参数个数=" + nums.length);
int res = 0;
for(int i = 0; i < nums.length; i++) {
res += nums[i];
}
return res;
}
}
public class VarParameterDetail {
//编写一个main方法
public static void main(String[] args) {
//细节: 可变参数的实参可以为数组
int[] arr = {1, 2, 3};
T t1 = new T();
t1.f1(arr);
}
}
class T {
public void f1(int... nums) {
System.out.println("长度=" + nums.length);
}
//细节: 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
public void f2(String str, double... nums) {
}
//细节: 一个形参列表中只能出现一个可变参数
//下面的写法是错的.
// public void f3(int... nums1, double... nums2) {
// }
}
public class VarParameterExercise {
//编写一个main方法
public static void main(String[] args) {
HspMethod hm = new HspMethod();
System.out.println(hm.showScore("milan" , 90.1, 80.0 ));
System.out.println(hm.showScore("terry" , 90.1, 80.0,10,30.5,70 ));
}
}
class HspMethod {
/*
有三个方法,分别实现返回姓名和两门课成绩(总分),
返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。
封装成一个可变参数的方法
*/
//分析1. 方法名 showScore 2. 形参(String ,double... ) 3. 返回String
//听课小伙伴,老师要求必须自己动手写
public String showScore(String name ,double... scores ) {
double totalScore = 0;
for(int i = 0; i < scores.length; i++) {
totalScore += scores[i];
}
return name + " 有 " +scores.length + "门课的成绩总分为=" + totalScore;
}
}
作用域
public class VarScope {
//编写一个main方法
public static void main(String[] args) {
}
}
class Cat {
//全局变量:也就是属性,作用域为整个类体 Cat类:cry eat 等方法使用属性
//属性在定义时,可以直接赋值
int age = 10; //指定的值是 10
//全局变量(属性)可以不赋值,直接使用,因为有默认值,
double weight; //默认值是0.0
public void hi() {
//局部变量必须赋值后,才能使用,因为没有默认值
int num = 1;
String address = "北京的猫";
System.out.println("num=" + num);
System.out.println("address=" + address);
System.out.println("weight=" + weight);//属性
}
public void cry() {
//1. 局部变量一般是指在成员方法中定义的变量
//2. n 和 name 就是局部变量
//3. n 和 name的作用域在 cry方法中
int n = 10;
String name = "jack";
System.out.println("在cry中使用属性 age=" + age);
}
public void eat() {
System.out.println("在eat中使用属性 age=" + age);
//System.out.println("在eat中使用 cry的变量 name=" + name);//错误
}
}
public class VarScopeDetail {
//编写一个main方法
public static void main(String[] args) {
Person p1 = new Person();
/*
属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。
局部变量,生命周期较短,伴随着它的代码块的执行而创建,
伴随着代码块的结束而销毁。即在一次方法调用过程中
*/
//p1.say();//当执行say方法时,say方法的局部变量比如name,会创建,当say执行完毕后
//name局部变量就销毁,但是属性(全局变量)仍然可以使用
//
T t1 = new T();
t1.test(); //第1种跨类访问对象属性的方式
t1.test2(p1);//第2种跨类访问对象属性的方式
}
}
class T {
//全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
public void test() {
Person p1 = new Person();
System.out.println(p1.name);//jack
}
public void test2(Person p) {
System.out.println(p.name);//jack
}
}
class Person {
//细节: 属性可以加修饰符(public protected private..)
// 局部变量不能加修饰符
public int age = 20;
String name = "jack";
public void say() {
//细节 属性和局部变量可以重名,访问时遵循就近原则
String name = "king";
System.out.println("say() name=" + name);
}
public void hi() {
String address = "北京";
//String address = "上海";//错误,重复定义变量
String name = "hsp";//可以
}
}
构造方法 构造器
快速入门
public class Constructor01 {
//编写一个main方法
public static void main(String[] args) {
//当我们new 一个对象时,直接通过构造器指定名字和年龄
Person p1 = new Person("smith", 80);
System.out.println("p1的信息如下");
System.out.println("p1对象name=" + p1.name);//smith
System.out.println("p1对象age=" + p1.age);//80
}
}
//在创建人类的对象时,就直接指定这个对象的年龄和姓名
//
class Person {
String name;
int age;
//构造器
//老韩解读
//1. 构造器没有返回值, 也不能写void
//2. 构造器的名称和类Person一样
//3. (String pName, int pAge) 是构造器形参列表,规则和成员方法一样
public Person(String pName, int pAge) {
System.out.println("构造器被调用~~ 完成对象的属性初始化");
name = pName;
age = pAge;
}
}
public class ConstructorDetail {
//编写一个main方法
public static void main(String[] args) {
Person p1 = new Person("king", 40);//第1个构造器
Person p2 = new Person("tom");//第2个构造器
Dog dog1 = new Dog();//使用的是默认的无参构造器
}
}
class Dog {
//如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
//使用javap指令 反编译看看
/*
默认构造器
Dog() {
}
*/
//一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,
//除非显式的定义一下,即: Dog(){} 写 (这点很重要)
//
public Dog(String dName) {
//...
}
Dog() { //显式的定义一下 无参构造器
}
}
class Person {
String name;
int age;//默认0
//第1个构造器
public Person(String pName, int pAge) {
name = pName;
age = pAge;
}
//第2个构造器, 只指定人名,不需要指定年龄
public Person(String pName) {
name = pName;
}
}
练习
public class ConstructorExercise {
//编写一个main方法
public static void main(String[] args) {
Person p1 = new Person();//无参构造器
//下面输出 name = null, age = 18
System.out.println("p1的信息 name=" + p1.name + " age=" + p1.age);
Person p2 = new Person("scott", 50);
//下面输出 name = scott, age = 50
System.out.println("p2的信息 name=" + p2.name + " age=" + p2.age);
}
}
/**
* 在前面定义的Person类中添加两个构造器:
* 第一个无参构造器:利用构造器设置所有人的age属性初始值都为18
* 第二个带pName和pAge两个参数的构造器:
* 使得每次创建Person对象的同时初始化对象的age属性值和name属性值。
* 分别使用不同的构造器,创建对象.
*/
class Person {
String name;//默认值 null
int age;//默认 0
//第一个无参构造器:利用构造器设置所有人的age属性初始值都为18
public Person() {
age = 18;//
}
//第二个带pName和pAge两个参数的构造器
public Person(String pName, int pAge) {
name = pName;
age = pAge;
}
}
对象创建流程分析 面试题
this关键字
public class This01 {
//编写一个main方法
public static void main(String[] args) {
Dog dog1 = new Dog("大壮", 3);
System.out.println("dog1的hashcode=" + dog1.hashCode());
//dog1调用了 info()方法
dog1.info();
System.out.println("============");
Dog dog2 = new Dog("大黄", 2);
System.out.println("dog2的hashcode=" + dog2.hashCode());
dog2.info();
}
}
class Dog{ //类
String name;
int age;
// public Dog(String dName, int dAge){//构造器
// name = dName;
// age = dAge;
// }
//如果我们构造器的形参,能够直接写成属性名,就更好了
//但是出现了一个问题,根据变量的作用域原则
//构造器的name 是局部变量,而不是属性
//构造器的age 是局部变量,而不是属性
//==> 引出this关键字来解决
public Dog(String name, int age){//构造器
//this.name 就是当前对象的属性name
this.name = name;
//this.age 就是当前对象的属性age
this.age = age;
System.out.println("this.hashCode=" + this.hashCode());
}
public void info(){//成员方法,输出属性x信息
System.out.println("this.hashCode=" + this.hashCode());
System.out.println(name + "\t" + age + "\t");
}
}
public class ThisDetail {
//编写一个main方法
public static void main(String[] args) {
// T t1 = new T();
// t1.f2();
T t2 = new T();
t2.f3();
}
}
class T {
String name = "jack";
int num = 100;
/*
细节: 访问构造器语法:this(参数列表);
注意只能在构造器中使用(即只能在构造器中访问另外一个构造器)
注意: 访问构造器语法:this(参数列表); 必须放置第一条语句
*/
public T() {
//这里去访问 T(String name, int age) 构造器
this("jack", 100);
System.out.println("T() 构造器");
}
public T(String name, int age) {
System.out.println("T(String name, int age) 构造器");
}
//this关键字可以用来访问本类的属性
public void f3() {
String name = "smith";
//传统方式
System.out.println("name=" + name + " num=" + num);//smith 100
//也可以使用this访问属性
System.out.println("name=" + this.name + " num=" + this.num);//jack 100
}
//细节: 访问成员方法的语法:this.方法名(参数列表);
public void f1() {
System.out.println("f1() 方法..");
}
public void f2() {
System.out.println("f2() 方法..");
//调用本类的 f1
//第一种方式
f1();
//第二种方式
this.f1();
}
}
public class TestPerson {
//编写一个main方法
public static void main(String[] args) {
Person p1 = new Person("mary", 20);
Person p2 = new Person("mary", 20);
System.out.println("p1和p2比较的结果=" + p1.compareTo(p2));
}
}
/*
定义Person类,里面有name、age属性,并提供compareTo比较方法,
用于判断是否和另一个人相等,提供测试类TestPerson用于测试,
名字和年龄完全一样,就返回true, 否则返回false
*/
class Person {
String name;
int age;
//构造器
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//compareTo比较方法
public boolean compareTo(Person p) {
//名字和年龄完全一样
// if(this.name.equals(p.name) && this.age == p.age) {
// return true;
// } else {
// return false;
// }
return this.name.equals(p.name) && this.age == p.age;
}
}
8章 2022年1月22日 - 9章 2022年1月24日
idea
包
命名规则
一个包下,包含很多的类,java 中常用的包有:
1) java.lang.* //lang 包是基本包,默认引入,不需要再引入.
2) java.util.* //util 包,系统提供的工具包, 工具类,使用 Scanner
3) java.net.* //网络包,网络开发
4) java.awt.* //是做 java
package com.hspedu.pkg;
import java.util.Arrays;
//注意:
//老韩建议:我们需要使用到哪个类,就导入哪个类即可,不建议使用 *导入
//import java.util.Scanner; //表示只会引入java.util 包下的 Scanner
//import java.util.*;//表示将java.util 包下的所有类都引入(导入)
public class Import01 {
public static void main(String[] args) {
//使用系统提供 Arrays 完成 数组排序
int[] arr = {-1, 20, 2, 13, 3};
//比如对其进行排序
//传统方法是,自己编写排序(冒泡)
//系统是提供了相关的类,可以方便完成 Arrays
Arrays.sort(arr);
//输出排序结果
for (int i = 0; i < arr.length ; i++) {
System.out.print(arr[i] + "\t");
}
}
}
//package的作用是声明当前类所在的包,需要放在类(或者文件)的最上面,
// 一个类中最多只有一句package
package com.hspedu.pkg;
//import指令 位置放在package的下面,在类定义前面,可以有多句且没有顺序要求
import java.util.Scanner;
import java.util.Arrays;
//...
//类定义
public class PkgDetail {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr = {0, -1, 1};
Arrays.sort(args);
}
}
访问修饰符
封装
package com.hspedu.encap;
public class Encapsulation01 {
public static void main(String[] args) {
//如果要使用快捷键alt+r, 需要先配置主类
//第一次,我们使用鼠标点击形式运算程序,后面就可以用
Person person = new Person();
person.setName("韩顺平");
person.setAge(30);
person.setSalary(30000);
System.out.println(person.info());
System.out.println(person.getSalary());
//如果我们自己使用构造器指定属性
Person smith = new Person("smith", 80, 50000);
System.out.println("====smith的信息======");
System.out.println(smith.info());
}
}
/*
那么在java中如何实现这种类似的控制呢?
请大家看一个小程序(com.hspedu.encap: Encapsulation01.java),
不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认
年龄, 必须在 1-120, 年龄, 工资不能直接查看 , name的长度在 2-6字符 之间
*/
class Person {
public String name; //名字公开
private int age; //age 私有化
private double salary; //..
public void say(int n,String name) {
}
//构造器 alt+insert
public Person() {
}
//有三个属性的构造器
public Person(String name, int age, double salary) {
// this.name = name;
// this.age = age;
// this.salary = salary;
//我们可以将set方法写在构造器中,这样仍然可以验证
setName(name);
setAge(age);
setSalary(salary);
}
//自己写setXxx 和 getXxx 太慢,我们使用快捷键
//然后根据要求来完善我们的代码.
public String getName() {
return name;
}
public void setName(String name) {
//加入对数据的校验,相当于增加了业务逻辑
if(name.length() >= 2 && name.length() <=6 ) {
this.name = name;
}else {
System.out.println("名字的长度不对,需要(2-6)个字符,默认名字");
this.name = "无名人";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
//判断
if(age >= 1 && age <= 120) {//如果是合理范围
this.age = age;
} else {
System.out.println("你设置年龄不对,需要在 (1-120), 给默认年龄18 ");
this.age = 18;//给一个默认年龄
}
}
public double getSalary() {
//可以这里增加对当前对象的权限判断
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//写一个方法,返回属性信息
public String info() {
return "信息为 name=" + name + " age=" + age + " 薪水=" + salary;
}
}
继承
细节
本质
package com.hspedu.extend_;
/**
* 讲解继承的本质
*/
public class ExtendsTheory {
public static void main(String[] args) {
Son son = new Son();//内存的布局
//?-> 这时请大家注意,要按照查找关系来返回信息
//(1) 首先看子类是否有该属性
//(2) 如果子类有这个属性,并且可以访问,则返回信息
//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到Object...
System.out.println(son.name);//返回就是大头儿子
//System.out.println(son.age);//返回的就是39
//System.out.println(son.getAge());//返回的就是39
System.out.println(son.hobby);//返回的就是旅游
}
}
class GrandPa { //爷类
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrandPa {//父类
String name = "大头爸爸";
private int age = 39;
public int getAge() {
return age;
}
}
class Son extends Father { //子类
String name = "大头儿子";
}
练习
//package com.hspedu.extend_.exercise;
//
//public class ExtendsExercise01 {
// public static void main(String[] args) {
// B b=new B();//a , b name, b
// }
//}
//
//class A {
// A() {
// System.out.println("a");
// }
//
// A(String name) {
// System.out.println("a name");
// }
//}
//
//class B extends A {
// B() {
// this("abc");
// System.out.println("b");
// }
//
// B(String name) {
// //默认有 super();
// System.out.println("b name");
// }
//}
//
super
比较
方法重写
多态
细节
动态绑定机制
多态数组
多态参数
object类详解
package com.hspedu.object_;
public class Equals01 {
public static void main(String[] args) {
A a = new A();
A b = a;
A c = b;
System.out.println(a == c);//true
System.out.println(b == c);//true
B bObj = a;
System.out.println(bObj == c);//true
int num1 = 10;
double num2 = 10.0;
System.out.println(num1 == num2);//基本数据类型,判断值是否相等
//equals 方法,源码怎么查看.
//把光标放在equals方法,直接输入ctrl+b
//如果你使用不了. 自己配置. 即可使用.
/*
//带大家看看Jdk的源码 String类的 equals方法
//把Object的equals方法重写了,变成了比较两个字符串值是否相同
public boolean equals(Object anObject) {
if (this == anObject) {//如果是同一个对象
return true;//返回true
}
if (anObject instanceof String) {//判断类型
String anotherString = (String)anObject;//向下转型
int n = value.length;
if (n == anotherString.value.length) {//如果长度相同
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {//然后一个一个的比较字符
if (v1[i] != v2[i])
return false;
i++;
}
return true;//如果两个字符串的所有字符都相等,则返回true
}
}
return false;//如果比较的不是字符串,则直接返回false
}
*/
"hello".equals("abc");
//看看Object类的 equals 是
/*
//即Object 的equals 方法默认就是比较对象地址是否相同
//也就是判断两个对象是不是同一个对象.
public boolean equals(Object obj) {
return (this == obj);
}
*/
/*
//从源码可以看到 Integer 也重写了Object的equals方法,
//变成了判断两个值是否相同
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
*/
Integer integer1 = new Integer(1000);
Integer integer2 = new Integer(1000);
System.out.println(integer1 == integer2);//false
System.out.println(integer1.equals(integer2));//true
String str1 = new String("hspedu");
String str2 = new String("hspedu");
System.out.println(str1 == str2);//false
System.out.println(str1.equals(str2));//true
}
}
class B {}
class A extends B {}