第七章
类与对象
类中包括属性和行为
定义类的属性和行为
对象的创建
new Cat()为创建一只猫,Cat cat1 = new Cat()为把创建的一只猫赋给cat1
cat1是一个对象
下面的语句为cat1的属性赋值
可以通过访问cat1来获得cat1中的属性
对象的内存布局
cat对象的名字存放在栈里面,栈中的地址指向了堆中的某个空间,堆中的数据空间有三个空间,三个空间用来存放对象cat的属性,但是因为对象cat的属性类型不同,其中还包括字符串类型的属性,因此属性存放在栈中的方式也不同,若属性类型为字符串类型,则堆中存放该属性的地址,地址指向方法区常量池中的一个空间,该空间中存放的才是字符串类型的属性;若属性类型为基本数据类型,则堆中存放的就是该属性
在执行创建对象的时候,会把类的信息加载到方法区
属性的叫法和类型
可以再定义属性前加修饰符,不同类型的属性有不同的默认值
创建对象的两种方法
第一种:先声明再创建
声明后
当new后num才会变成一个地址
第二种:直接创建
对象之间的赋值规则
将对象p1赋给p2,实际上是让p2指向p1所指向的地址,p1与p2同时指向堆中的同一个空间
若将null赋给对象
b指向的地址会变为空,不再指向原来的空间,但是不会改变a所指的地址,a指向的空间存放的数据不变
方法
定义一个方法
public代表这是个公开的方法,void代表没有
()代表没有形参传入
方法写好后,若不去调用,则不会输出
调用方法
带形参的方法
(int n)表示当前有一个形参n,用来接收用户的输入
对象调用带形参的方法
调用带形参的cal02方法,同时给形参n赋值n=5
同一个对象可以对次吊用同一个方法,如p1.cal02(5);
p1.cal02(10);
带返回值且有两个形参的方法及其调用
方法getSum前的int代表会方法getSum会返回一个int型的值,p1.getSum(10,20)得到的是整型的30,再用一个变量去接收30
方法调用机制
由于对象的创立和方法的调用都在main方法中,所以在栈中的main栈开始执行语句
首先创建对象会在堆中创建一个对象
执行到int re…=…时,先执行=号右边的对象调用方法语句,执行该语句时(调用方法时)会在栈中开辟另外一个空间,称为getSum栈,并且根据对象名和方法名定位到该方法的位置,并将10,20按顺序赋值给num1和num2
赋值完后继续执行res=n1+n2
当执行到retuen res时,会将res的值返回给调用该方法的对象(根据对象调用方法时留下的地址)p1.getSum,然后getSum栈销毁
返回类型为数组的方法
当返回类型为数组类型时,要用数组来接收
方法的细节
- 一个方法只能有一个返回值,若要返回多个值可以返回数组
- 返回类型可以为基本数据类型或引用类型
- 若返回值类型不是void,则方法体最后一个语句一定要为return … return后面可以为变量或者表达式
- 返回数据类型必须和return后面的值一致或兼容,如pubic double …,方法体中int n = 1;return n;也可以,由小到大,自动类型转换
void,方法体中没有return或者return后面不带任何返回值
方法中形参列表的细节
3.
传入参数兼容
传入参数不兼容
4.实参和形参
方法调用时传入的参数是实参,实际的参数;方法定义时的参数为形参
实参顺序不对导致的错误
方法调用的细节
1.同一个类中的方法可以直接调用
2.跨类方法的调用,需要用创建对象再调用
A类中的方法调用B类中的方法,需要在A类的方法中创建一个B类的对象,再用该对象调用B类中的方法
3.能都调用别的类的方法还和访问修饰符public与是否在同一个包中有关
写方法前的注意事项:
主方法中的a和b与swap方法中的a和b不冲突,两组a,b作用于不同的作用空间
形参的不同数据类型
传入基本数据类型给形参(值拷贝)
传入引用类型的数据(数组或者对象)给形参(传入地址),会影响原来引用类型的内容,形参的修改影响实参
b类中test100接收一个数组,再对其进行修改,在main方法中调用完test100这个方法后,由于传入给test100的是arr1[]数组的地址,因此在main中再次遍历arr1[]数组后,会发现arr1[]会被修改
当在方法中使对象p指向空时,不会改变原来p指向的空间的数据
p = null只是执行了p指向空地方的操作,并没有修改p中属性的数据
方法递归
先创建对象,创建完后传入参数4到test中,此时n=4,判断n>2是否成立,成立,执行test(n-1)即调用test方法,进行方法的递归,将3传给test(),继续判断n>2,成立,执行test(n-1);将n=2传给test(),判断n>2,不成立,输出System…n=2;返回上一层test(n-1)的位置,继续执行下面的代码,注意此时的n应为这个test栈的n,输出System…n=3……
用递归实现阶乘
返回值每次都返回给上一层调用方法的位置
递归的规则
方法的重载
可以允许多个同名方法的存在,但要求形参列表不一样(形参类型,数量,顺序)
PrintStream是一个类,out是该类的对象
方法重载的细节
是否为方法的重载主要看形参列表是否不同
形参列表相同,返回类型不同也造成方法的重复定义
错误,不是方法的重载
三元运算符
n1是否大于n2,是的话返回n1,否则返回n2
可变参数
可变参数的使用:数据类型… 形参名,代表可传入多个int类型的实参
可变参数的使用
可变参数的形参名,可代表数组名,和数组的使用规则一样,再用遍历来进行求和
可变参数的细节
1.传入的实参可以是数组,可变参数本质就是数组 2.可变参数可以和普通类型形参放在形参列表,但要保证可变参数放在最后 3.形参列表只能出现一个可变参数
作用域
局部变量一般是指在成员方法中定义的变量
两个变量只作用在cry方法中
全局变量
全局变量也就是属性,属性在定义时,可以直接赋值,并且全局变量的作用域在整个类中,类中的所有方法都可以使用
全局变量(属性)由于有默认值所以不用赋值,可以直接使用;局部变量没有默认值不能直接使用,hi方法中会报错
作用域的细节
局部变量和全局变量可以重名
全局变量可以被其它类使用(2种方法)
方法一:
在其它类的方法中通过建立全局变量所在类的对象来调用全局变量
方法二:
在其他类的方法中接收一个全局变量所在类的对象,通过该对象来调用
注意:局部变量只能在本类的方法中使用,且不能加修饰符
全局变量(属性)可以加修饰符(public protected private..)