Java笔记5
目录
对象的产生
当一个对象被创建时,会对其中各种类型成员变量自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型,如笔记3的Person以及之前的笔记2的数组
匿名对象
我们也可以不定义对象的句柄,直接调用这个对象的方法,这样的对象叫做匿名对象
如: new Person().shout();
使用情况
如果我们对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
我们经常将匿名对象作为实参传递给一个方法调用。
举例:利用面向对象的编程设计方法设计类Circle计算圆的面积。
//Circle.java
/**
* 计算圆的面积
* @author Mwq
*
*/
public class Circle {
/**
* 面积的计算方法
* @param r 圆的半径
* @return
*/
public double area(double r) {
return 3.14*r*r;
}
}
//Text12.java
public class Text12 {
public static void main (String[] args) {
double area =new Circle().area(2);
System.out.println("半径为2的圆的面积是:"+area);
}
}
//输出结果:
// 半径为2的圆的面积是:12.56
提示类的访问机制:
(1)在一个类的访问机制中:类中的方法可以直接访问类中的成员变量。(例外:static方法访问非static的成员变量,编译不通过。)
(2)在不同类的访问机制中:先要访问类的对象,再用对象访问类中定义的成员。
面向对象思想“落地”发展(1)
1.关注于类的设计,即设计类的成员:属性、方法
2.类的实例化,即创建类的对象(比如:Person p= new Person();)
3.通过”对象.属性“、”对象.方法“ 执行
方法的重载(overload)
举例:
(1)定义三个重载方法并调用,方法名为mOL,三个方法分别接收一个int参数,两个int参数,一个字符串参数,分别执行平方运算输出结果,相乘并输出结果,输出字符串信息。在主类main()方法中分别用参数区别调用三个方法。
(2)定义三个重载方法max(),第一个方法求两个int值中的最大值,第二个方法求两个double值中的最大值,第三方法求三个double值中的最大值,并分别调用三个方法。
public class Text12 {
public static void main (String[] args) {
//测试数据
t12.mOL(2);
t12.mOL(2,3);
t12.mOL("重载方法");
t12.max(0,1);
t12.max(0.2,1.5);
t12.max(9.1, 5.2, 2.3);
}
//多个相同名称的方法如果想在一个类中共存,那么这些同名方法一定是参数的个数或者参数的数据类型不一样
//这样的同名方法叫做重载
public int add(int x,int y) {
return x+y;
}
public double add(int x,double y) {
return x+y;
}
public int add(int x,int y, int z) {
return x+y+z;
}
public void mOL(int i) {
System.out.println(i*i);
}
public void mOL(int x,int y) {
System.out.println(x*y);
}
public void mOL(String s) {
System.out.println(s);
}
public void max(int x,int y) {
if(x>y) {
System.out.println("最大值:"+x);
}else {
System.out.println("最大值:"+y);
}
}
public void max(double x,double y) {
double res=0;
if(x>y) {
res=x;
}else {
res=y;
}
System.out.println("最大值:"+res);
}
public void max(double x,double y,double z) {
double res=0;
if(x>y) {
if(x>z) {
res=x;
}else {
res=z;
}
}else {
if(y>z) {
res=y;
}else {
res=z;
}
}
System.out.println("最大值是:"+res);
}
}
//输出结果:
/* 4
6
重载方法
最大值:1
最大值:1.5
最大值是:9.1
*/
体会可变个数的形参
//下面采用数组形参来定义方法
public static void test(int a,String[] books);
//以可个数形参来定义方法
public static void test(int a,String...books);
说明:
1.可变参数:方法参数部分指定类型的参数个数是可变多个
2.声明方式:方法名(参数的类型名…参数名)
3.可变参数方法二等使用与方法参数部分使用数组是一致对的
4.方法的参数部分有可变形参,需要放在形参声明的最后
举例:
//两者使用方法结果一样,...是java特有的,和数组模式类似
//Person3.java
public class Person3 {
/**
* 用数组的方式传递可变个数的参数
* 如果没有参数,就要定义一个空数组或者是null
* @param args
*/
public void printInfo(String[] args) {//我们现在能打印的信息都来源于方法的参数就是形参的传递
//如果给方法传递不同参数,如果不知道想要给方法传递的参数个数(姓名,性别,年龄;身份证号码;家庭住址)
for(int i=0;i<args.length;i++) {
System.out.println(args[i]);
}
}
/**
* 用java特有的...的方式来传递可变个数的参数,这种参数在使用时与数组的使用相同
* 如果没有参数可以不填
* 这种..代表可以传递0到多个参数
* 如果一个方法有多个的形参,可变的形参(...这种的)一定要放在所有的形参最后
* printInfo1(String s,int d,String... args)这样的放置参数的方式是对的
* printInfo1(String s,String...,int d args)这样的放置参数的方式是不对的
* printInfo1(String... args,String s,int d)这样的放置参数的方式是不对的
* @param args
*/
public void printInfo1(String... args) {
for(int i=0;i<args.length;i++) {
System.out.println(args[i]);
}
}
}
//Text5.java
//测试实现
public class Texe5 {
public static void main(String[] args) {
Person3 p3=new Person3();
String[] ss=new String[] {"zhangsan","11"};
p3.printInfo(ss);
String[] ss1=new String[] {"北京市","13131313221","1561616165156156"};
p3.printInfo(ss1);
p3.printInfo1("lisi","23","man");
String[] ss2=new String[] {"2-2-3","1213","呼声"};
p3.printInfo1(ss2);
p3.printInfo1();//如果没有参数可以不填
p3.printInfo(null);//如果没有参数,就要定义一个空数组或者是null
}
}
/*输出结果:
zhangsan
11
北京市
13131313221
1561616165156156
lisi
23
man
2-2-3
1213
呼声
*/
方法的参数传递
方法只有在被其所在类或对象调用才有意义。
方法含有的参数:
形参:方法声明时的参数
实参:方法调用时实际传给形参的参数值
java的实参值如何传入方法呢?
java里面方法的参数传递方式只有一种:值传递。即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
JVM的内存模型
(1)Person p=new Person()的地址存放过程:
先把堆里面存放new Person()对象的二进制地址(BE34434)
p在栈中的地址是AG6464存的是对象的二进制地址(BE34434)这就加引用对象
(重要)方法的参数传递之基本数据类型:
public class Text6 {
public static void swap(int i) {
i=6;
System.out.println("swap方法中的参数i的值:" + i);
}
public static void main(String[] args) {
int a=0;
swap(a);
System.out.println("main方法中的a的值:"+a);
}
}
//先执行int a=0,在栈中开辟了一块内存,地址就是AD8500,存的值是0
//然后调用swap方法,执行int部分,在栈中开辟一块内存,地址是AD8600,值就是从a那里复制过来的值,就是0,执行swap的方法体里面的代码,i=6,把i在栈中的值再改为6,最终i在栈中的值为6.
/* 输出结果
swap方法中的参数i的值:6
main方法中的a的值:0
*/
总而言之,基本数据类型在参数传递过程中,就是把实参的值复制值到形参上。
(重要)方法的参数传递之引用对象:
//Text7.java
public class Text7 {
public static void swap(DataSwap ds1) {
ds1.a=6;
System.out.println("在swap方法中,ds1.a的值是:"+ds1.a);
}
public static void main(String[] args) {
DataSwap ds=new DataSwap();
System.out.println("调用swap方法之前,da.a的值是:"+ds.a);
swap(ds);
System.out.println("调用swap方法之后,da.a的值是:"+ds.a);
}
}
//DataSwap.java
public class DataSwap {
public int a;
}
/*输出结果:
调用swap方法之前,da.a的值是:0
在swap方法中,ds1.a的值是:6
调用swap方法之后,da.a的值是:6
*/
传递地址参数的基本过程:
1.DataSwap ds=new DataSwap();,把new DataSwap()存到了堆内存中,地址BE2500
2.ds引用对象存到栈中,地址是AD9500,值是newDataSwap()对象在堆中的地址 BE2500
3.调用swap方法,得ds1引用对象保存到栈中,地址是AD9600,存的值来源于实参(ds),也就是ds栈中存的值就是new DataSwap()对象在堆内存中的地址
到第3步的时候,实际上,ds、ds1其实都是指向同一个对象,这个对象就是在堆内存中地址是BE2500上保存的对象,ds、ds1是引用对象,存的是对象实际在堆中的地址,堆内存里面的BE2500是对象实际存储的地方。
这个例子里面ds和ds1操作的实际是同一个对象。
方法参数传递总结
1.如果方法的形参是基本数据类型,那么实参(实际的数据)向形参传递参数时,就是直接传递值,把实参的值复制给形参。
2.如果方法的形参是对象,那么实参(实际的对象),向形参传递参数时,也是把值给形参,这个值是实参在栈内存中的值,也就是引用对象在堆内存中的地址。
基础数据类型的值保存在栈中,引用对象值保存在堆中,在栈中保存的是对象在堆中的地址,那么方法的参数传递是传递值(是变量在栈内存的当中的值)