Java 入门 3
1.方法
方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集
1.1 Java中方法的的定义格式
分为两种情况:
1)有具体返回值类型的方法定义
2)无具体返回值类型的方法定义
1)有具体返回值类型的方法定义 固定格式: 权限修饰符 static 返回值类型 方法名(形式参数类型1 变量名1,形式参数类型2 变量2....){ //功能业务操作 return 结果; } public static 返回值类型 方法名(形式参数类型1 变量名1,形式参数类型2 变量2....){ //功能业务操作 return 结果; } 解释: 权限修饰符:现在方法访问权限:公共的/公开的,访问权限足够大,public static:面向对象在讲,目前来说必须带上static 返回值类型:数据类型 (目前使用的基本类型) 方法名:见名知意,满足标识符的规则...(小驼峰命名法) 形式参数类型:数据类型(目前使用的基本类型) 变量名:定义参数名称 (见名知意)满足标识符的规则...(小驼峰命名法) 有具体返回值类型的方法调用: 方法名(实际参数) ; 1)单独调用:没有输出结果 2)输出调用:可以用,不建议用,因为如果需要将结果进一步操作,写死,不太好! 3)赋值调用:推荐 有返回值类型方法调用:赋值调用 返回值类型 变量名 = 方法名(实际参数名1,实际参数名2....); *两个明确* 1)明确返回值类型 2)明确参数类型以及参数个数 Java中定义方法和调用方法的注意事项(有返回值类型的方法) 1)方法和方法是平级关系,在一个方法中不能嵌套定义另一个方法 2)Java是一个强类型语言,定义方法的时候,形式参数类型必须携带,不能省略! 3)调用方法的时候,实际参数不需要携带数据类型的 4)定义方法的时候,后面千万不能来一个分号,这个方法缺少方法主体的,没有意义! 有{左大括号的地方不能有分号; 有;号的地方不能有{左大括号 public static int add(int a,int b); { 没有意义 return a + b ; }
2)没有具体返回值类型的方法定义 按照方法的定义格式: 固定格式: 权限修饰符 静态修饰符static 返回值类型 方法名(形式参数列表...){ .. } "直接在控制台打印数据" 没有具体返回值,Java有一个规定, 遵循上面方法定义格式,使用关键字void 代替了返回值类型(只是为了填充语法格式) 没有具体返回值类型方法定义格式:固定写法 public static void 方法名(参数类型1 变量名1,参数类型2 变量名2....){ 输出语句/或者数据交换... } 没有具体返回值类型方法调用: 1)单独调用:推荐! 方法名(实际参数列表) ; 2)输出调用:不行 3)赋值调用:不行
1.2 方法重载
Java中多个方法的功能如果一样的,那么这些方法名字可以同名-----> 方法重载(OverLoad) 多个方法名相同,参数列表不同,与返回值无关
参数列表不同: 1)参数个数不同 2)参数类型不同 3)考虑类型顺序
方法重载的目的:就是为了让这个功能扩展性更多;方法中接收常用的一些数据类型参数
1.3 应用
//用方法表示n*n乘法表 import java.util.Scanner; public class Chen{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); System.out.println("请输入1-9的数字"); int n = sc.nextInt(); getNum(n); } public static void getNum(int a){ for(int x =1;x<=a;x++){ for(int y = 1;y<=x;y++){ System.out.print(x+"*"+y+"="+x*y+"\t"); } System.out.println(); } } }
2. 数组
数组是只能够存储同一种类型的容器,在同一数组中,元素的数据类型必须一致
数组定义格式: 数据类型[] 数组名称; 例:int[] arr; 数据类型 数组名称[] ; 例:int arr[]; 数据类型:学习基本数据类型
2.1 数组初始化
1)动态初始化:
我们给定数组的长度,元素由系统(Jvm)默认初始化
数据类型[] 数组名称 = new 数据类型[长度] ; (推荐第一种) 数据类型 数组名称[] = new 数据类型[长度] ;
例: class ArrayDemo{ public static void main(String[] args){ //创建一个数组:动态初始化 //数据类型[] 数组名称 = new 数据类型[长度] ; int[] arr = new int[3] ;//jvm系统默认对3个初始化 //解析格式: //=左边: //int:数组中存储的int数据类型 //[]:数组:一维数组(默认) //arr:变量名(数组的在内存中的对象名称) //=右边 //new:表示创建对象 //int:表示存储的数据int类型 //[3]:数组中存储的3个元素:(长度) System.out.println(arr) ; //[I@6d06d69c :地址值 //[:表示一维数组 //I:int数据类型 //@:地址值标记 //6d...:十六进制数据 System.out.println("-----------------------") ; //数组名称[索引值]:索引值从0开始 //默认初始化 System.out.println(arr[0]) ;//访问数组第一个元素 0 System.out.println(arr[1]) ;//访问数组第二个元素 0 System.out.println(arr[2]) ;//访问数组第三个元素 0 System.out.println("-----------------------") ; //显示初始化了 arr[0] = 10 ; arr[1] = 20 ; arr[2] = 50 ; System.out.println(arr[0]) ;//访问数组第一个元素 10 System.out.println(arr[1]) ;//访问数组第二个元素 20 System.out.println(arr[2]) ;//访问数组第三个元素 50 System.out.println(arr) ; } }
*如何访问数组的元素呢? 数组名称 [索引值] : 索引值从0开始
2)静态初始化:
我们给出具体的元素内容,系统默认分配长度
数据类型[] 数组名称 = new int[]{元素1,元素2,元素3,.....} ; 推荐第一种 数据类型 数组名称[] = new int[]{元素1,元素2,元素3,.....} ;
简化格式:书写代码简单 数据类型[] 数组名称 = {元素1,元素2,元素3,.....} ; 数据类型 数组名称[] = {元素1,元素2,元素3,.....} ;
举例: int[] arr = new int[]{1,2,3,4,5,6} ; 简化格式: int[] arr = {1,2,3,4,5,6} ;
注意事项: 数组的初始化:要么动态初始化/要么静态初始化,不能"动静结合" int[] arr = new int[3]{1,2,3} ; 错误的!
2.2 补充
数组就是引用类型,引用类型下面经常会出现异常: 运行时期异常: ArrayIndexOutOfBoundsException:数组角标越界异常 NullPointerException:空指针异常 程序在过程中,经常会出现"异常"; 程序有问题 1)编译时期异常:jvm检查语法不通过; 语法格式存在问题 举例: 同一个变量被定义多次 数组格式写错 ... 2)运行时期异常:开发者:代码书写不严谨导致的问题 键盘录入:代码书写---->录入int类型 int num = 键盘录入对象.nextInt() ; java.lang.ArrayIndexOutOfBoundsException:数组角标越界异常 出现的原因:访问了数组中不存在的角标(索引值) 如何解决:检查代码,更改索引值 java.lang.NullPointerException:空指针异常 引用类型的默认值都是null; String s = null ; 字符串是一种特殊的引用类型 出现的原因:某一个对象已经为空了,null(没有堆内存地址),这个时候还要去访问元素或者调用 这个对象的方法,那么就出现空指针; 如何解决: 使用逻辑判断语句,对该对象进行非空判断
2.3 数组的应用
1) 数组遍历:
就是元素内容一一获取出来,使用它完成需求!
//数组中有一个默认的属性:length属性:可以获取数组的长度 //数组对象名.length:获取数组的长度 //数组的最大索引值:是数组长度-1 /* 方式1: 普通格式输出 定义一个遍历数组的功能 两个明确 1)明确返回值类型:直接输出元素,没有具体返回值类型 void 2)明确参数类型以及参数个数 int[],1个 */ public static void printArray(int[] arr){//形式参数 for(int x = 0 ; x < arr.length ; x ++){ System.out.println(arr[x]) ; } /* 方式2:输出按照一种优雅的格式 定义一个遍历数组的功能 两个明确 1)明确返回值类型:直接输出元素,没有具体返回值类型 void 2)明确参数类型以及参数个数 int[],1个 */ public static void printArray2(int[] arr){ //先输出"[" System.out.print("[") ; //遍历这个arr数组 for(int x = 0 ; x < arr.length ; x++){ //判断:如果当前x的取值:取到了arr.length-1:数组的最大索引值 if(x==arr.length-1){ //最后一个元素以及"]" System.out.println(arr[x]+"]") ; }else{ //不是最后一个元素,中间的元素 System.out.print(arr[x]+", ") ; } } }
2) 数组最值问题:求最大值或者最小值
分析: 1)创建一个数组,静态初始化 获取数组中的最大值的思路 2)定义参照物:假设思想 将数组中的第一个元素作为最大值 3)遍历其他元素,依次这个参照物进行比较,如果后面元素比它大,后面的元素就最大值 4)输出结果即可! 最小值:同理
class ArrayTest2{ public static void main(String[] args){ //创建一个数组,静态初始化 int[] arr = {69,27,58,13,24,98,76} ; //定义一个参照物,作为最大值(假设为最大值) int max = arr[0] ; //遍历其他元素, for(int x = 1 ;x < arr.length; x ++){ //一一获取到角标1以及后面的所有角标对应的元素 //依次使用这些元素和参照物进行比较 if(arr[x] > max){ //后面的元素就是最大值 max = arr[x] ; } } System.out.println("数组中的最大值是:"+max) ; System.out.println("----------------------------------------") ; //调用:获取数组中的最大值的方法 int max2 = getMax(arr) ; System.out.println("数组中最大值是:"+max2) ; System.out.println("----------------------------------------") ; int min = getMin(arr) ; System.out.println("数组中最小值是:"+min) ; } /* 定一个方法:获取数组中的最小值 两个明确 1)明确返回值类型:int类型, 2)明确参数类型以及参数个数 int[]的数组,1个参数 */ public static int getMin(int[] arr){ //定义一个参照物 int min = arr[0] ; //遍历其他元素 for(int x = 1; x < arr.length; x++){ //如果后面的元素比min小,就是最小值 if(arr[x] < min){ min = arr[x] ; } } return min ; } /* 定义一个方法:获取数组中的最大值的方法 两个明确 1)明确返回值类型:int类型,具体的最大值 2)明确参数类型以及参数个数 int[]的数组,1个参数 */ 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 ; } }
3) 数组元素逆序
分析: 将arr[0]元素和arr[arr.length-1]互换 将arr[1]元素和arr[arr.length-2]互换 .. .. 保证最终数组的长度 arr.length/2
class ArrayTest3{ public static void main(String[] args){ //创建数组,静态初始化 int[] arr = {64,87,56,18,24} ; System.out.println("数组逆序前:") ; printArray(arr) ; System.out.println("-----------------------------") ; System.out.println("数组逆序后:") ; //方式1: //reverse(arr) ; //方式2: reverse2(arr) ; //借助于遍历功能 printArray(arr) ; } public static void reverse2(int[] arr){ //定义两个变量 //start:起始索引:0开始 //end:最终索引:arr.length-1 for(int start = 0,end = arr.length-1; start < end; start++,end--){ //定义中间变量 //元素互换 int temp = arr[start] ; //temp = arr[0 ] arr[start] = arr[end] ;//arr[0] = arr[arr.length-1] ; arr[end] = temp ;//arr[arr.length-1] = temp ; } } public static void reverse(int[] arr){ /* 将arr[0]元素和arr[arr.length-1]互换 将arr[1]元素和arr[arr.length-2]互换 .. .. 保证最终数组的长度 arr.length/2 */ //第一次互换 //定义中间变量 //将arr[0]元素和arr[arr.length-1]互换 /* int temp = arr[0] ; arr[0] = arr[arr.length-1-0] ; arr[arr.length-1-0] = temp ; //第二次互换 temp = arr[1] ; arr[1] = arr[arr.length-1-1] ; arr[arr.length-1-1] = temp ; //...... //...... */ //优化代码:上面代码冗余度很高,循环思想改进 for(int x = 0 ; x < arr.length/2; x ++){ //互换 int temp = arr[x] ; //arr[0] arr[x] = arr[arr.length-1-x] ; //arr[arr.length-1-0] ; arr[arr.length-1-x] = temp ; } } /* 定义一个数组遍历的功能 */ public static void printArray(int[] arr){ System.out.print("[") ; //遍历数组 for(int x = 0 ; x < arr.length;x ++){ //判断角标x是否为最大索引值 if(x== arr.length-1){ System.out.println(arr[x]+"]") ; }else{ //输出元素并且,拼接空格 System.out.print(arr[x]+", ") ; } } } }
4) 数组的元素查表法:
最简单的查询 数组名称 [索引值] 访问元素
/* 需求: 键盘录入一个数据(0-6),查询数组的元素,输出星期... 分析: 1)已知字符串数组 数据类型[] 数组名称= {"元素1","元素2",...} ; String[] strArray = {"星期一","星期二","星期三","星期四","星期五", "星期六","星期日"}; 2)输出结果strArray[索引值] ; */ import java.util.Scanner ; class ArrayTest4{ public static void main(String[] args){ //创建一个字符串数组对象,静态初始化 String[] strArray = {"星期一","星期二","星期三","星期四","星期五","星期六","星期日"}; //创建键盘录入对象 Scanner sc = new Scanner(System.in) ; //提示并录入数据 System.out.println("请您输入一个数据(0-6):") ; int num = sc.nextInt() ; System.out.println("您要查找的是:"+strArray[num]) ; //角标从0开始 } }
数组的应用: 基本元素查找法:查询数组中的某个元素出现第一次出现索引值 传统方式查找:从头查询到尾,数组的元素可以有序,可以无序! 分析: 1)数组,静态初始化 int[] arr = {62,29,87,56,13,24} ; 2)查询24这个元素在数组中第一次出现索引值 3)将查询这个元素的索引值----使用方法来完成 定义这个方法 两个明确: 1)明确返回值类型:int 2)明确参数类型以及参数个数: int[]数组,int元素 2个参数 class ArrayTest{ public static void main(String[] args){ //创建数组,静态初始化 int[] arr = {62,29,87,56,13,24} ; //调用一个功能:获取数组中元素的角标值 int index = getIndex(arr,24) ; System.out.println("index:"+index); System.out.println("----------------") ; int index2 = getIndex(arr,666) ; System.out.println("index2:"+index2); System.out.println("----------------") ; //方式2测试: int index3 = getIndex2(arr,56) ; System.out.println("index3:"+index3); int index4 = getIndex2(arr,251) ; System.out.println("index4:"+index4); } //方式2:定义一个功能 //假设法 public static int getIndex2(int[] arr,int target){ //假设思想: //定义一个角标值index int index = -1 ; //遍历数组,获取元素 for(int x = 0 ; x < arr.length ; x ++){ //判断:如果target元素和arr[x]一致找到了 if(target == arr[x]){ //更改index角标 index = x ; break ; //结束 } } return index ; } //定义一个方法 //target = 500 :数组中不存在元素,for循环结束了,都没有返回值,方法报错! public static int getIndex(int[] arr,int target){ //参数1:在指定数组中找,参数2:查找的元素 //遍历这个数组获取到每一个元素 for(int x = 0 ; x < arr.length; x++){ //判断:如果target和arr[x]一致,表示找到了 if(target==arr[x]){ return x ; //返回 } } //找不到 return -1 ; //负数:代表找不到元素 } }
5) 数组高级排序算法之冒泡:
思想: 两两比较,将较大的值往后放,第一次比较完毕,最大值就出现在最大索引处 依次这样比较,即可得到排好序的数组...
public class Num { public static void main(String[] args) { int[] arr = {15,20,2,4,65,12,75}; System.out.println("自定义数组为:"); Num1(arr); System.out.println("数组重组后为:"); Num2(arr); Num1(arr); } public static void Num1(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]+", "); } } } public static void Num2(int[] arr){ for(int x = 0;x<arr.length-1;x++){ for(int y = 0;y<arr.length-1-x;y++){ if(arr[y]>arr[y+1]){ int temp = arr[y]; arr[y] = arr[y+1]; arr[y+1] = temp; } } } } }
3. Java中内存分配
栈内存: 存储局部变量,在方法定义中或方法声明上的变量
堆内存: new出来的东西(创建对象)
方法区: class文件区/ static静态域/常量区....
本地方法区: (和系统相关)
寄存器:(给CPU使用)
局部变量生命周期:随着方法的调用而存在,随着方法调用结束而结束
*对象一但创建,地址值是固定的,除非重新new
栈结构:先进后出
进栈方式:压栈
出栈方式:弹栈
*基本数据类型作为"形式参数" 传递特点:形式参数的改变不会影响实际参数!
*引用类型作为形式参数特点: 形式参数的改变,会直接影响实际参数, String类类型除外(它的效果和基本数据类型) 数组,类,接口
4.面向对象
1) 什么是面向对象?
詹姆斯高斯林Java之父 ("万物皆对象")
阐述下面向对象思想特点 + 结合我们中生活中的例子!
2) 面向对象的思想特点: 1)更符合我们生活中思想行为习惯 2)让更复杂的事情简单化 3)角色发生了变化:我们从执行者变成了指挥者!
3) Java语言:面向对象语言---->它的设计原则
在程序中(符合生活中的场景),不断的创建对象,使用对象,指挥对象做事情(完成功能...)
举例: 1. 创建键盘录入对象:Scanner 2. 录入int类型/String类型数据
4) Java语言面向对象的三大特征
封装,继承,多态!
4.1 类
概念: 能够描述一组事物的属性和行为的集合---->类
类------>能够描述现实世界真实存在的 "事物"
现在使用Java代码的方式 描述现实世界存在的事物 Java中最基本的单元:类-----> 事物 成员变量-------> 描述事物的属性 成员方法(非静态的)-------> 描述事物的行为 成员变量: 在类中,方法外; 成员方法: 之前怎么定义方法,现在还怎么写,不过,去掉static关键字 public 返回类型 方法名(形式参数列表){ 业务体 //有具体结果1)return 结果 ; //没有具体结果:输出 打印... } 定义: 两个明确 1)明确返回值 :有-->给具体类型 ,没有:void 代替 输出结果 2)明确参数类型,以及参数个数 具体情况,具体分析
4.1.1 类与对象的关系
类----描述真实事物的 学生事物 属性: 姓名 年龄 住址 .. 行为: 学习JavaSE 学生类 class Student{ //成员变量 ---事物属性 String name ;//姓名 int age ;//年龄 String address;//住址 //... //成员方法----事物的行为 public void study(String name){ System.out.println("正在学习"+name) ; } } 什么是对象? 体现出 "具体的事物" 因为类---描述事物----概括的事物("总称") 具体的学生:圆圆,42,鄠邑区 在测试类中使用:main方法所在类 代码体现: 格式: 类名 对象名 = new 类名() ; 给具体事物属性赋值 对象名.成员变量 = 根据类型赋值; 调用具体事物的行为 对象名.成员方法名() ;
class Student{ //定义成员变量(描述属性) :类中方法外 //学号,姓名,年龄,性别,住址 String sId;//学号 String name ; //姓名 int age ; //年龄 String gender ; //性别 String address ;//住址 //定义成员方法:(描述行为) :去掉static,非静态的! //学习JavaSE public String study(String className){//"JavaSE" return "正在学习"+className ; } //玩游戏 //直接打印 public void playGame(){ System.out.println("学习困了,玩一把lol,但是不要沉迷...") ; } //抽华子(抽烟功能) public String smoke(String name){//"华子" return "这个学生抽的是"+name ; } } //学生类的测试类 class StudentTest{ public static void main(String[] args){ // 格式: //类名 对象名 = new 类名() ; //创建了一个具体的学生对象 Student s = new Student() ; //之前最早开始使用键盘录入的固定格式:每次键盘录入的Scanner sc = new Scanner(System.in) ; //int num = sc.nextInt() ; //描述具体的学生事物: 学生名字,年龄,性别.... /* 给具体事物属性赋值 对象名.成员变量 = 根据类型赋值; 调用具体事物的行为 对象名.成员方法名() ; */ s.sId = "s9527" ; s.name = "高圆圆" ; s.age = 42 ; s.gender = "女" ; s.address = "鄠邑区" ; //输出结果 System.out.println("该学生的学号是"+s.sId+ ",姓名是:"+s.name+",年龄是:"+s.age+",性别为:"+s.gender+",所在的住址是:"+s.address) ; //调用功能 String result = s.study("JavaSE") ; System.out.println(result) ; s.playGame() ; System.out.println(s.smoke("华子")) ; } }
4.1.2 局部变量和成员变量区别
1)在类中的书写位置区别 局部变量:在方法定义中或者是方法声明上; 成员变量:在类中,方法外;
2)在内存中的位置不同 局部变量:在栈内存中 成员变量:在堆内存中 3)生命周期不同: 局部变量:随着方法调用而存在,随着方法调用结束而消失 成员变量:随着对象的创建而存在,随着对象的调用完毕,等待垃圾回收器空闲时候回收,不会立即消失! 4)初始化时机不同: 局部变量: 要么先定义,使用之前必须初始化;要么直接初始化 成员变量: 可以不赋值,系统默认对成员变量初始化 也可以通过对象名.成员变量 =赋值;
4.1.3 形式参数问题_研究引用类型
//定义一个学生类 class Student{ public void study(){ System.out.println("Good Good Study,Day Day Up!!") ; } } //定义一个类StudentDemo类 class StudentDemo{ //有一个成员方法,形式参数是Student类型 public void method(Student s){//Student student = new Student() ;//形式参数:如果一个方法的形式参数是一个类,实际参数需要传递的当前类的具体对象 s.study() ; //student.study(); } } //定义一个测试类 class StudentTest{ public static void main(String[] args){ //需求: //1)要访问StudentDemo类中的method方法? //2)调用的时候,实际参数如何书写呢? //要访问StudentDemo类的method方法,创建当前类对象来访问 StudentDemo sd = new StudentDemo() ; //形式参数:如果一个方法的形式参数是一个类,实际参数需要传递的当前类的具体对象 //创建当前类对象:Student student = new Student() ; Student student = new Student() ; sd.method(student); } }
4.1.4 匿名对象
匿名对象: 顾名知意:没有名字的对象
创建对象的格式: 类名 对象名 = new 类名() ; Student s = new Student() ;
匿名对象的格式: new 类名() ; 好处: 1)节省内存空间 2)开发中,匿名对象一般 使用"一次即可",使用完毕就立即垃圾回收器回收! 3)手机移动端/Android/鸿蒙系统:基于Java语言 ios系统:基于c语言
访问类的成员变量: new 类名().成员变量名; 访问类的成员方法:没有具体返回值类型 new 类名().成员方法名() ;
//例:学生类 class Student{ public void study(){ System.out.println("好好学习,天天向上...") ; } } //定义一个类:StudentDemo class StudentDemo{ //show方法里面形式参数是引用类型:具体的类Student public void show(Student s){ s.study() ;//new Student().study(); } } //测试类 class NoNameDemo{ public static void main(String[] args){ //需求:访问StudentDemo类中的show方法 //1)创建当前StudentDemo类对象 StudentDemo sd = new StudentDemo() ; //调用show() Student s = new Student() ; sd.show(s) ; //实际参数需要创建Student类的对象 System.out.println("-----------------------------------------") ; //匿名对象的格式: //new 类名() ; //需求:访问StudentDemo类中的show方法 StudentDemo sd2 = new StudentDemo() ; sd2.show(new Student()) ; System.out.println("-----------------------------------------") ; //一步走:链式编程:仅仅是自己玩一玩足矣 new StudentDemo().show(new Student()) ; } }
4.2 封装
1) private:私有的,不能直接访问的; 特点: 被private修饰的成员变量或者是成员方法,只能在本类中访问; 外界类是不能直接访问的,间接可以通过公共的成员方法访问!
2)权限修饰符: private :最小 public: 最大
3)封装:
为了保证类的属性的安全性,所有的属性都必须加入private关键字, 并且对外提供公共的访问方法间接的对成员变量(属性)进行赋值; setXXX()/getXXX():都是public的:权限足够大 总结:属性私有化,对外提供给公共的成员方法访问方法:setXXX()/getXXX()
//定义一个Demo类 class Demo{ //公共的成员变量 public int num = 100 ; private int num2 = 200 ; //定义一个公共方法 public void show(){ System.out.println(num) ; System.out.println(num2) ; } //定义一个公共的成员方法 public void method(){ System.out.println("hello,method...") ; System.out.println("------------------------") ; function(); } //定义一个私有的成员方法 private void function(){ System.out.println("hello,function...") ; } } //测试类 class PrivateDemo{ public static void main(String[] args){ //需求:访问Demo类的num //创建Demo类对象 Demo d = new Demo() ; System.out.println(d.num) ; System.out.println("--------------------------") ; //System.out.println(d.num2) ;//错误: num2 在 Demo 中是 private 访问控制 //通过公共方法间接访问私有的成员变量 d.show() ; System.out.println("--------------------------") ; //对象名.成员方法名(); d.method() ; //间接访问公共访问---访问的私有方法; //d.function();// function() 在 Demo 中是 private 访问控制 } }
4.3 this
上面的代码存在弊端: 讲标识符:在实际开发中,起名字(变量/方法/类)见名知意 当前代码中的setXXX(形式参数):都是 n,a,g,i,h:不太合适 既然见名知意: name,赋值一个姓名 age:赋值年龄 gender:赋值性别 id:赋值学号 hobit:赋值爱好
局部变量名称和成员变量名称一致(局部变量隐藏了成员变量), Java提供了一个关键字:this
*this:代表当前类对象的地址值引用
//定义学生类 class Student{ //成员变量私有化; private String name ;//姓名 private int age ;//年龄 private String gender ;//性别 private String id ;//学号 private String hobit ;//爱好 //对外提供的公共访问方法:setXXX()/getXXX() //给学生姓名赋值 /* public void setName(String n){ //n:赋值的姓名 name = n ; //"高圆圆" } */ //改造之后 public void setName(String name){ //name赋值的姓名 //访问成员变量 = 局部变量; this.name = name ; //"高圆圆" //上面代码存在问题:局部变量名称和成员变量名称一致 //加入this之后,格式变成this.xx=xx; } //获取学生的姓名 public String getName(){ return name ;//"高圆圆" getXXX()方法里面隐藏this //return this.name ; //省略this :就是上面的写法 } //给学生年龄赋值 /* public void setAge(int a){//42 age = a ; //42 } */ //改造之后 public void setAge(int age){ this.age = age ; } //获取学生的年龄 public int getAge(){ return age ;//42 } //给学生的性别赋值 /* public void setGender(String g){//"女" gender = g ;//"女" } */ //改造之后 public void setGender(String gender){//"女" this.gender = gender ;//"女" } //获取学生的性别 public String getGender(){ return gender ;//"女" } //给学生的学号赋值 /* public void setId(String i){//"9527" id = i ; //"9527" } */ //改造之后 public void setId(String id){//"9527" this.id = id ; //"9527" } //获取学生的学号 public String getId(){ return id ;//"9527" } //给学生的爱好赋值 /* public void setHobit(String h){//"踢球" hobit = h ; //"踢球" } */ public void setHobit(String hobit){//"踢球" this.hobit = hobit ; //"踢球" } //获取学生的爱好 public String getHobit(){ return hobit ;//"踢球" } //其他成员方法 //study(),playFootball(),watchMove() public void study(String name){ System.out.println("我们正在学习"+name) ; } public void playFootball(){ System.out.println("喜欢踢足球...") ; } } //测试类 class StudentTest2{ public static void main(String[] args){ //创建学生类对象 Student s = new Student() ; //setXXX()赋值 s.setName("张佳宁") ; s.setAge(31) ; s.setGender("女") ; s.setId("it001") ; s.setHobit("打台球...") ; System.out.println(s.getName()+"---"+ s.getAge()+"---"+s.getGender()+"---"+s.getId()+"---"+s.getHobit()) ; //调用其他成员方法... }
4.4 构造方法
一个类的成员: 成员变量--->私有化(封装) 成员方法
新的成员:构造方法
1) 什么是构造方法: 构造方法是一种特殊的方法,方法名和类名一致;
2) 特点: 1)方法名和类名一致; 2)构造方法没有返回值类型 3)连void都没有 *构造方法是重载的!
3) 分类: 无参构造方法:没有参数 有参构造方法:有具体的参数类型 4) 构造方法的作用:就是对类中的数据(成员属性)进行初始化
//定义了一个学生类 class Student{ //显示给出了 无参构造方法 public Student(){ System.out.println("这是Student类的无参构造方法...") ; } //有参构造方法 public Student(String name){ System.out.println("这是Student类的带String类型的有参构造方法...") ; } //带两个参数的构造方法 public Student(String name,int age){ System.out.println("这是带两个参数的有参构造方法....") ; } } //测试类 class ConstructorDemo{ public static void main(String[] args){ //创建学生类对象 Student s = new Student() ; System.out.println(s) ;//Student@6d06d69c /* 这是Student类的无参构造方法... Student@6d06d69c */ System.out.println("---------------------------") ; //创建学生对象 Student s2 = new Student("高圆圆") ; System.out.println(s2) ; System.out.println("---------------------------") ; //在创建学生对象 Student s3 = new Student("高圆圆",42) ; System.out.println(s3) ; /* 这是带两个参数的有参构造方法.... Student@4e25154f */ } }
5) 构造方法的注意事项: 1.当我们开发者既没有提供无参构造方法,也没有提供有参构造方法, 系统永远给我们提供 "无参构造方法" 类名 对象名 = new 类名() ; //创建对象的格式
2.如果我们提供了有参构造方法,那么系统不会在提供无参构造方法
构造方法的作用:给类的成员属性可以进行数据初始化 给成员变量(私有修饰)赋值几种方式: 1.公共的访问方法setXXX(xx):赋值 2.有参构造方法进行赋值 public 类名(参数类型1 变量名1,参数类名2 变量名2...){ this.成员变量名1 = 变量1; this.成员变量名2 = 变量2 ; ... }