无参和有参构造方法:
1.构造方法和方法重载
如:
Person p = new Person(); - 声明Person类型的引用指向Person类型的对象
p.show(); - 使用引用变量p调用show方法
/*
自定义Point类,特征有:横坐标和纵坐标,行为有:无参构造和有参
// 构造以及打印所有特征的方法
// 要求在main方法中分别使用无参和有参方式构造对象并打印特征
*/
public class Point
{
int Abscissa;
int Ordinate;
void show(){
System.out.println("横坐标:"+Abscissa+";"+"纵坐标:"+Ordinate);
}
//无参
Point(){
}
//有参
Point(int a,int b){
Abscissa=a;
Ordinate=b;
}
public static void main(String[] args){
Point p=new Point();
p.show();
Point p1=new Point(10,20);
p1.show();
}
}
1.1 构造方法(重中之重)
(1)语法格式
class 类名 {
类名(形参列表) {
构造方法体;
}
}
如:
class Person {
Person() {
}
}
(2)注意事项
a.构造方法的名称与类名完全相同,没有返回值类型连void都不许有。
b.当使用new关键字构造对象时会自动调用构造方法进行成员变量的初始化工作。
(3)默认构造方法
a.当一个类中没有自定义任何形式的构造方法时,编译器会自动添加一个无参的
空构造方法,叫做默认/缺省构造方法,如:Person(){}
b.若类中出现自定义构造方法,则编译器不再提供任何形式的构造方法。
无特殊要求都要在类里构造两个方法,一个有参一个无参
建议自定义无参构造方法,不要对编译器形成依赖,避免错误发生。
当类中有非常量成员变量时,建议提供两个版本的构造方法,一个是无参构造方法,一个是全属性做参数的构造方法。
当类中所有成员变量都是常量或者没有成员变量时,建议不提供任何版本构造
1.2 方法的重载(Overload 会用即可)
(1)基本概念
在Java语言中若方法的名称相同但参数列表不同,这样的方法之间构成重载关系。
(2)体现形式
方法重载的主要形式有:参数的个数不同、参数的类型不同、参数的顺序不同,与形参变量名和返回值类型无关,但建议返回值类型最好相同。
判断方法是否重载的核心:调用能否区分。
(3)实际意义
对于调用者来说只需要记住一个方法名就可以调用各种不同的版本实现不同的效果。
如:
char c = ‘a’;
System.out.println©;
int i = 10;
System.out.println(i);
double d = 3.14;
System.out.println(d);
…
/*
作业要求:
编程实现为Point类添加重载的成员方法:
up() – 实现纵坐标减1的功能。
up(int dy) – 实现纵坐标减去参数指定数值的功能。
测试重载方法的调用规则
*/
public class Point1
{
int x;
int y;
void up(){
y--;
}
void up(int dy){
y-=dy;
}
void show(){
System.out.println("横坐标"+x+"纵坐标"+y);
}
public static void main(String[] args){
Point1 p=new Point1();
p.x=50;
p.y=70;
p.show();
p.up();
p.show();
p.up(20);
p.show();
}
}
2.this关键字(原理、理解)
2.1 基本概念
在构造方法中this关键字代表当前正在构造的对象。
在成员方法中this关键字代表当前正在调用的对象。
原理分析:
当成员方法中访问成员变量时默认会加上this.(相当于汉语中"我的"),当不同的引用调用同一个成员方法时会导致成员方法中的this不同,那么this.访问的结果随之不同。
2.2 使用方式
(1)当形参变量和成员变量同名时,在构造方法或成员方法中通常优先使用形参变量,若希望使用成员变量就需要在变量名的前面加上this.进行说明(重中之重)。
(2)在构造方法的第一行使用this(实参)的方式可以调用本类中的其它构造方法(了解)
/*作业要求:
问题描述
1.重点理解和掌握Person类的所有代码。
2.自定义Car类,
特征有:品牌(brand)、颜色(color)、价格(price),
行为有:
无参构造、
三个参数的构造、
打印所有特征的行为、
获取品牌并返回的行为、
获取颜色并返回的行为、
获取价格并返回的行为、
设置品牌为参数指定的数值、
设置颜色为参数指定的数值、
设置价格为参数指定的数值、
实现价格增长1000元的行为、
实现价格增长参数指定数值的行为。*/
public class Car
{ //特征
String brand;
String color;
int price;
//无参构造
Car(){}
//三个参数的构造
Car(String brand,String color,int price){
this.brand=brand;
this.color=color;
this.price=price;
}
//打印所有特征的行为
void show(){
System.out.println("品牌:"+brand+"颜色:"+color+"价格:"+price);
}
//获取品牌并返回的行为
String getB(){
return brand;
}
String getC(){
return color;
}
//获取价格并返回的行为
int getP(){
return price;
}
//设置品牌为参数指定的数值
void setB(String x){
brand=x;
}
//设置颜色为参数指定的数值、
void setC(String y){
color=y;
}
//设置价格为参数指定的数值、
void setP(int z){
price=z;
}
//实现价格增长1000元的行为、
void setP(){
price+=1000;
}
//实现价格增长参数指定数值的行为
void setP1(int a){
price+=a;
}
public static void main(String[] args){
Car tt=new Car();
tt.show();
Car tt1=new Car("SF90","yellow",4900000);
tt1.show();
System.out.println("-------------------------");
String ia=tt1.getB();
System.out.println("车的品牌为:"+ia);
String ib=tt1.getC();
System.out.println("车的颜色为:"+ib);
int ic=tt1.getP();
System.out.println("车的价格为:"+ic);
System.out.println("-------------------------");
tt1.setB("BMW");
tt1.show();
tt1.setC("red");
tt1.show();
tt1.setP(5000000);
tt1.show();
System.out.println("-------------------------");
tt1.setP();
tt1.show();
System.out.println("-------------------------");
tt1.setP1(50000);
tt1.show();
}
}
//编程实现this方法
public class ThisTest
{
ThisTest(){
//在构造方法中出现this代表当前正在构造的对象
System.out.println("构造方法:this"+this);
}
void show(){
//在成员方法中出现this代表当前正在调用的对象
System.out.println("成员方法中:this"+this);
}
public static void main(String[] args){
ThisTest tt =new ThisTest();
tt.show();
System.out.println("main方法中:tt="+tt);
System.out.println("---------------------");
ThisTest tt1 =new ThisTest();
tt1.show();
System.out.println("main方法中:tt1="+tt1);
}
}
3.方法的传参和递归调用
3.1 方法的传参过程(理解)
(1)main方法是程序的入口,为main方法中的局部变量开辟内存空间并初始化;
(2)调用max方法时为max方法的形参变量开辟内存空间;
(3)使用实参变量给形参变量进行赋值操作,执行max方法的方法体;
(4)当max方法结束后释放形参变量的内存空间;
(5)main方法中的res得到max方法的返回值然后继续向下执行;
(6)当main方法结束后释放局部变量的内存空间;
注意:Java中的方法可以传递参数,参数的传递方法就是值传递。
参数有形参和实参,定义方法时写的参数叫形参,真正调用方法时,传递的参数叫实参。调用方法时,会把实参传递给形参,方法内部其实是在使用形参。
所谓值传递就是当参数是基本类型时,传递参数的值,比如传递i=10,真实传参时,把10赋值给了形参。当参数是对象时,传递的是对象的值,也就是对象的首地址。就是把对象的地址赋值给形参。
参数传递的步骤:
1 分配实参空间,基本类型在栈中赋值,引用类型变量在栈中指向堆中的对象
2 传递参数其实就是在栈中分配形参的空间,然后把栈中实参的值复制过来。
3 在方法中使用形参,方法结束形参出栈(消失),只剩下实参。
gc主要针对堆中的对象,栈中数据是随时进出的。判断堆中对象是不是内存垃圾的条件看栈中是否有指向,直接或者间接的指向都可以,没有的就是内存垃圾
要求大家掌握的内容:
a.当基本数据类型的变量作为方法的参数传递时,形参变量的改变不会影响到实参;
b.当引用数据类型的变量作为方法的参数传递时,形参变量指向的内容发生改变后会影响到实参变量指向的内容;
c.当引用数据类型的变量作为方法的参数传递时,形参变量改变指向后再改变指向的内容时不会影响到实参变量指向的内容;
//应用数据类型作为参数的传递分析实现
public class Brr
{ //基本数据类型
void show(int a){
a=100;
System.out.println("a="+a);//a=100
}
//引用型形参
void show(int[] brr){
brr=new int[2];//加上该行代码后的执行结果 因为brr 在堆区新开了空间。指向不在和arr为同一内存地址
brr[0]=200;
System.out.println("brr[0]="+brr[0]);//brr[0]=200
}
public static void main(String[] args){
//a. 当基本数据类型的变量作为方法的参数传递时,形参变量的改变不会影响到实参;
Brr at=new Brr();
int num=10;
at.show(num);
System.out.println("num="+num);#num=10
System.out.println("-----------------------------" );
//b.当引用数据类型的变量作为方法的参数传递时,形参变量的指向的内容发生改变后会影响到实参变量指向的内容;
int[] arr=new int[]{20,30};
at.show(arr);
System.out.println("arr[0]="+arr[0]);#arr[0]20
}
}
3.2 递归调用(难点)
(1)基本概念
在一个方法体的内部调用当前方法自身的形式,叫做递归。
如:
void show(){
show();
}
案例:
自定义成员方法实现参数n阶乘的计算并返回。
解析:
5! = 5 * 4 * 3 * 2 * 1;
4! = 4 * 3 * 2 * 1;
3! = 3 * 2 * 1;
2! = 2 * 1;
1! = 1;
n! = n * (n-1) * (n-2) * … * 1;
5! = 5 * 4!;
4! = 4 * 3!;
3! = 3 * 2!;
2! = 2 * 1!;
1! = 1;
n! = n * (n-1)!;
//自定义成员方法实现参数n阶乘的计算并且返回
public class Jechen
{
//自定义成员方法实现参数n阶乘的计算并且返回
void show(int n){
/*
int res=1;
//递推
for(int i =n;i>0;i--){
res*=i;
}
retrurn res*/
if(1==n){
return 1;
}
return n*show(n-1);
}
public static void main(String[] args){
Jechen jie=new Jechen();
int num=jie.show(5);
System.out.println("最终的阶乘为"+num);
}
}
(2)注意事项
a.必须找到递归的规律和退出条件;
b.使用递归使得问题简单化而不是复杂化;
c.若递归影响到程序的执行性能则使用递推取代之;
/*作业要求:
问题描述
1.重点理解和掌握Person类的所有代码。
2.自定义Car类,
特征有:品牌(brand)、颜色(color)、价格(price),
行为有:
无参构造、
三个参数的构造、
打印所有特征的行为、
获取品牌并返回的行为、
获取颜色并返回的行为、
获取价格并返回的行为、
设置品牌为参数指定的数值、
设置颜色为参数指定的数值、
设置价格为参数指定的数值、
实现价格增长1000元的行为、
实现价格增长参数指定数值的行为。*/
public class Car
{ //特征
String brand;
String color;
int price;
//无参构造
Car(){}
//三个参数的构造
Car(String brand,String color,int price){
this.brand=brand;
this.color=color;
this.price=price;
}
//打印所有特征的行为
void show(){
System.out.println("品牌:"+brand+"颜色:"+color+"价格:"+price);
}
//获取品牌并返回的行为
String getB(){
return brand;
}
String getC(){
return color;
}
//获取价格并返回的行为
int getP(){
return price;
}
//设置品牌为参数指定的数值
void setB(String x){
brand=x;
}
//设置颜色为参数指定的数值、
void setC(String y){
color=y;
}
//设置价格为参数指定的数值、
void setP(int z){
price=z;
}
//实现价格增长1000元的行为、
void setP(){
price+=1000;
}
//实现价格增长参数指定数值的行为
void setP1(int a){
price+=a;
}
public static void main(String[] args){
Car tt=new Car();
tt.show();
Car tt1=new Car("SF90","yellow",4900000);
tt1.show();
System.out.println("-------------------------");
String ia=tt1.getB();
System.out.println("车的品牌为:"+ia);
String ib=tt1.getC();
System.out.println("车的颜色为:"+ib);
int ic=tt1.getP();
System.out.println("车的价格为:"+ic);
System.out.println("-------------------------");
tt1.setB("BMW");
tt1.show();
tt1.setC("red");
tt1.show();
tt1.setP(5000000);
tt1.show();
System.out.println("-------------------------");
tt1.setP();
tt1.show();
System.out.println("-------------------------");
tt1.setP1(50000);
tt1.show();
}
}