day07:
1、包的作用
(1)避免类的重名
(2)组织管理不同层(不同模块)的类 bean、service、dao、test等
(3)可以限定部分类或成员的可见性范围
2、如何声明包
package 包名;
要求:
(1)一个.java文件只能有一句package语句,而且必须在代码首行
(2)如果某个.java文件声明了package语句,那么这个.java文件必须在对应的目录结构中。
包==>文件夹/目录
3、包名的命名规则和规范
(1)命名规则和其他的标识符一样
(2)命名规范
所有单词都小写,每一个单词之间使用.分割,每一个.代表一级目录。
例如:com.atguigu.pkg ==> com/atguigu/pkg
(3)命名习惯
公司域名倒置 + 具体的功能模块名
例如:com.atguigu.xxx
4、类如何跨包使用
只要两个.java文件的 package语句不完全相同,就认为是不同的包。
package com.atguigu.pkg;
package com.atguigu.other;
它们是不同的包
(1)方式一:使用类的全名称:包.类名
(2)方式二:使用import语句导包
import 包.类名;
import 包.*; //这里*代表的是省略的类名,不能省略子包名
实例变量的内存分析
分析:对象的成员变量(这里主要指实例变量)的内存
JVM的运行的内存:
(1)方法区:存储被加载的类的模板信息、常量等
(2)堆:存储new出来的对象信息
(3)JAVA虚拟机栈:存储Java的方法局部变量等
(4)本地方法栈:存储C/C++等方法的局部变量
(5)程序计数器:存储每一个线程的下一条指令等
new在堆中申请内存空间,存储这个对象的相关信息。
每一个对象需要存储三个部分的内容:
(1)对象头
(2)对象的实例变量值
(3)对齐的空白(这个有的对象可能没有)
this
Student.java
package com.atguigu.method;
public class Student {
String name;
int age;
int score;
//声明一个方法,自我介绍,返回当前学生对象自己的属性值
public String introduce(){
//这里的this指的是调用introduce()的对象
// return "姓名:" + this.name +",年龄:" + this.age +",成绩:" + this.score;
//没有重名问题,歧义问题,可以省略this.
//说明 本类的成员方法可以直接使用本类自己的成员变量
return "姓名:" + name +",年龄:" + age +",成绩:" + score;
}
}
TestStudent.java
package com.atguigu.method;
public class TestStudent {
public static void main(String[] args) {
//1、创建学生对象
Student s = new Student();
//在给s对象的属性赋值之前,调用Student类的introduce()方法
System.out.println(s.introduce());//直接输出返回值
s.name = "张三";
s.age = 23;
s.score = 89;
//再次调用s对象的introduce()方法
System.out.println(s.introduce());
Student s2 = new Student();
System.out.println(s2.introduce());
}
}
方法调用内存分析
方法不调用不执行,调用一次执行一次,每次调用会在栈中有一个入栈动作,即给当前方法开辟一块独立的内存区域,用于存储当前方法的局部变量的值,当方法执行结束后,会释放该内存,称为出栈,如果方法有返回值,就会把结果返回调用处,如果没有返回值,就直接结束,回到调用处继续执行下一条指令。
栈结构:先进后出,后进先出。
package com.atguigu.test04.method;
public class MethodMemory {
public static void main(String[] args) {
Rectangle r1 = new Rectangle();
Rectangle r2 = new Rectangle();
r1.length = 10;
r1.width = 2;
r1.print('#');
System.out.println("r1对象:" + r1.getInfo());
System.out.println("r2对象:" + r2.getInfo());
}
}
实例变量与局部变量的区别
1、声明位置和方式
(1)实例变量:在类中方法外
(2)局部变量:在方法体{}中或方法的形参列表、代码块中
2、在内存中存储的位置不同
(1)实例变量:堆
(2)局部变量:栈
3、生命周期
(1)实例变量:和对象的生命周期一样,随着对象的创建而存在,随着对象被GC回收而消亡,
而且每一个对象的实例变量是独立的。
(2)局部变量:和方法调用的生命周期一样,每一次方法被调用而在存在,随着方法执行的结束而消亡,
而且每一次方法调用都是独立。
4、作用域
(1)实例变量:通过对象就可以使用,本类中“this.,没有歧义还可以省略this.”,其他类中“对象.”
(2)局部变量:出了作用域就不能使用
5、修饰符(后面来讲)
(1)实例变量:public,protected,private,final,volatile,transient等
(2)局部变量:final
6、默认值
(1)实例变量:有默认值
(2)局部变量:没有,必须手动初始化。其中的形参比较特殊,靠实参给它初始化。
形参与实参
package com.atguigu.param;
/*
参数:
1、形参:在“声明”方法时,()中声明的变量,每调用这个方法之前,它的值是不确定的。
例如:
public int max(int a, int b){ //(int a,int b)是形参,它就是一个占位符,形式。
return a>b ?a:b;
}
形参代表未知的数据,需要调用者传入实际的数据,它才有意义。
定义形参,就是为了让方法体的代码顺利编写,否则无法描述这个未知的数据。
2、实参:在“调用”方法时,()中传入的数据,这个数据可能是常量值,也可能是变量,还可能是表达式
3、形参和实参的关系
(1)实参给形参赋值,实参会把值复制给形参
(2)实参的类型、个数必须和形参一一对应
*/
public class TestParam {
public int max(int a, int b){ //(int a,int b)是形参,它就是一个占位符,形式。
return a>b ?a:b;
}
public int biggest(int a, int b ,int c){//找三个整数的最大值,形参(int a, int b ,int c)
return max(max(a,b),c);//
//第一次调用max方法,a,b是实参
//第二次调用max方法, max(a,b)的返回值是实参之一,c是另一个实参
}
public static void main(String[] args) {
TestParam t = new TestParam();
System.out.println(t.max(4,6));//(4,6)是实参,4,6是常量,它给(int a, int b)两个形参赋值
int x = 5;
int y = 7;
System.out.println(t.max(x,y));//(x,y)是实参,x,y是变量,它用x,y中的值给(int a, int b)两个形参赋值
int z = 4;
//比较x和y,z的最大值
System.out.println(t.biggest(x,y,z));
}
}
可变参数(重要!!!)
MathTools.java
package com.atguigu.param;
//案例:写一个方法可以求n个整数的和
public class MathTools {
/* public int sum(int[] nums){//(int[] nums)形参
int he = 0;
for (int i = 0; i < nums.length; i++) {
he += nums[i];
}
return he;
}*/
public int sum(int... nums){//(int... nums)形参
int he = 0;
for (int i = 0; i < nums.length; i++) {
he += nums[i];
}
return he;
}
}
StringTools.java
package com.atguigu.param;
//写一个方法实现n个字符串进行拼接,每一个字符串之间使用某字符进行分割,如果没有传入字符串,那么返回空字符串""
public class StringTools {
//String... strings是可变参数,可以传入0~n个的元素
//但是char seperator不是可变参数,调用时必须传入对应类型的实参
public String concat(char seperator, String... strings){
if(strings == null || strings.length==0){
return "";
}
String result = "";
for (int i = 0; i < strings.length; i++) {
if(i<strings.length-1) {
result += strings[i] + seperator;
}else{
result += strings[i];
}
}
return result;
}
}
TestVarParam.java
package com.atguigu.param;
1、可变参数:
参数:形参和实参
可变:实参的个数可变
2、可变参数的语法格式
数据类型... 参数名
3、要求
(1)每一个方法,最多只能有一个可变参数
(2)可变参数必须是方法的最后一个参数
4、如何使用可变参数
(1)在声明可变参数的方法中,把它当数组中即可
(2)在调用包含可变参数的方法时,可变参数对应的实参可以传入
A:对应类型的数组
B:对应类型的0~n个元素
案例:写一个方法可以求n个整数的和
public class TestVarParam {
public static void main(String[] args) {
MathTools t = new MathTools();
//求3个整数的和,1,2,3
int[] arr = {1,2,3};
System.out.println(t.sum(arr));
System.out.println(t.sum(1,2,3));
//求5个整数的和,1,2,3,4,5
System.out.println(t.sum(new int[]{1,2,3,4,5}));
System.out.println(t.sum(1,2,3,4,5));
//求0个整数的和
System.out.println(t.sum(new int[0]));//长度为0的数组
System.out.println(t.sum());
System.out.println("=====================");
StringTools tools = new StringTools();
System.out.println("没有字符串:" + tools.concat('-'));
System.out.println("3个字符串:" + tools.concat('-',"hello","world","atguigu"));
}
}
n个整数中的最小值和n个整数的最大公约数
package com.atguigu.exer.param;
/*
1、n个整数中的最小值和n个整数的最大公约数
(1)声明方法int min(int... nums):返回n个整数中的最小值
(2)声明方法int maxApproximate(int... nums):返回n个整数的最大公约数
*/
public class ParamExer1 {
public static void main(String[] args) {
Tools tools = new Tools();
System.out.println("5个整数的最小值是:" + tools.min(8,9,3,7,2));
System.out.println("5个整数的最大公约数:" + tools.maxApproximate(8,6,12,18,20));
}
}
package com.atguigu.exer.param;
public class Tools {
int min(int... nums){
int minValue = nums[0];//这句代码有问题,当没有传入数字时,nums[0]不存在,会发生空指针异常
for (int i = 1; i < nums.length; i++) {
if(nums[i] < minValue){
minValue = nums[i];
}
}
return minValue;
}
int maxApproximate(int... nums){
int min = min(nums);//找出它们中最小的
int result = 1;
for(int i=min; i>=1; i--){
boolean flag = true;
for (int j = 0; j < nums.length; j++) {
if(nums[j]%i!=0){
flag = false;//说明i不是它们的公约数
break;
}
}
if(flag){
result = i;
break;
}
}
return result;
}
}