06面向对象(初级)类与对象、成员方法与传参机制、重载、可变参数、作用域、构造器、this
目录
类与对象
张老太养了两只猫猫:一只名叫小白,今年三岁,白色。还有一只叫小花,今年一百岁,花色。请编写一个程序:
当用户输入小猫名字时,就显示:该猫的名字,年龄,颜色。
如果用户输入的小猫名错误,则显示:张老太没有这只猫猫
单独变量来解决→不利于数据的管理(把一只猫的信息拆解了)
第一只小猫的信息
String cat1Name = "小白";
int cat1Age = 3;
String cat1Color = "白色";
数组→1、体现不出来数据类型2、只能通过[下标]获取信息,造成变量名字和内容的对应关系不明确3不能体现猫的行为
第一只猫和第二只猫的信息
String[] cat1 = {"小白","3","白色"};
使用现有技术解决:
1单独的定义变量解决
2使用数组解决
现有技术解决的缺点:
不利于数据的管理
效率低→引出类与对象
java设计者引入类与对象(oop),根本原因就是现有的技术,不能完美的解决新的需求。
从类到对象,目前有几种说话:
1、创建一个对象 2、实例化一个对象 3、把类实例化
如何创建对象
1先声明在创建
Cat cat;
cat = new Cat();
2直接创建
Cat cat = new Cat();
java创建对象的流程简单分析
Person p = new Person();
p.name = "jack";
p.age = 10;
1先加载person类信息(属性和方法信息,只会加载一次)
2在堆中分配空间,进行默认初始化(看规则)
3把地址赋给p,p就指向对象
4进行指定初始化,比如p.name="jack";p.age=10;
类和对象的内存分配机制:
java内存的结构分析
1栈:一般存放基本数据类型(局部变量)
2堆:存放对象(Cat cat,数组等)
3方法区:常量池(常量,比如字符串),类加载信息
1、区别和联系
1类是抽象的,概念的,代表一类事物,比如人类,猫类。。。即它是数据类型。
2对象时具体的,实际的,代表一个具体事务
3类是对象的模板,对象时类的一个个体
2、属性/成员变量
1基本介绍从概念或叫法上看:成员变量=属性=field(成员变量是表示属性的)
2属性是类的一个组成部分,一般是基本数据类型(对象,数组)。
3、注意事项和细节说明
1属性的定义语法同变量
2属性的定义类型可以为任意类型,包含基本类型或引用类型
3属性如果不赋值,有默认值,规则和数组一致
练习题:
看下面一段代码,会输出什么:
Person a = new Person();
a.age = 10;
a.name = "小明";
Person b;
b=a;
System.out.println(b.name);//小明
b.age = 200;
b = null;
System.out.println(a.age);//200
System.out.println(b.age);//异常
成员方法
基本介绍:
在某些情况下,我们需要定义成员方法(简称方法)。比如人类:除了有一些属性外(年龄,名字)我们人类还有一些行为如:可以说话,走路。这时就要用成员方法从才能完成。
成员方法的好处
提高代码的复用性
可以将实现的细节封装起来,然后提供其他用户来调用即可
成员方法的定义
public 返回数据类型 方法名 (形参列表..){//方法体
语句;
return 返回值;
}
1、形参列表:标识成员输入cal(int n),getSum(int num1,int num2)
2、返回数据类型:表示成员方法输出,void表示没有返回值
3、方法主体:表示为了实现某一功能代码块
4、return 语句不是必须的
注意事项和使用细节
返回类型
1、一个方法最多一个返回值[如何返回多个结果:返回数组]
2、返回类型可以为人以类型,包含基本类型或引用类型(数组,对象)
3、如果方法要求有返回数据类型,则方法体中的执行语句必须为return 值;而且要求返回值类型必须和return的值类型一致或兼容
4、如果方法是void,则方法体重可以没有return语句,或者只写 return;
形参列表:
1、一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开。
2、参数类型可以为任意类型。包含基本类型或引用类型
3、调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
4、方法定义时的参数称为形式参数,简称形参;方法调用时的参数称为实际参数,简称实参,实参和新参的类型要一致或兼容、个数、顺序必须一致
方法体:
里面写完成功能的具体语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能在定义方法。即:方法不能嵌套定义
方法细节调用说明
1、同一个类中的方法调用:直接调用即可。
2、跨类中的方法A类调用B类方法:需要通过对象名调用。如:对象名.方法名(参数)
3、特别说明一下:跨类的方法调用和方法的访问修饰符相关。
练习题
1编写类AA新方法:判断一个数是奇数还是偶数,返回boolean
2根据行列字符打印对应行数和列数的字符,比如行:4,列:4,字符#,则打印相应效果
成员方法传参机制
案例:
B类中编写一个方法test100,可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化。
B类中编写一个方法test200,可以接受一个Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变化。
B b = new B();
int[] arr = {1,2,3};
b.test100(arr);
System.out.println("MethodParameter01 arr数组");
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
//测试
Person p = new Person();
p.name = "jack";
p.age = 10;
b.test200(p);
System.out.println("main的age="+p.age);//100
//B类中编写一个方法test200
//可以接受一个Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变化
class Person{
String name;
int age;
}
class B{
public void test200(Person p){
p.age = 100;//修改对象属性
}
//B类中编写一个方法test100
//可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化
public void test100(int[] arr){
arr[0] = 100;
System.out.println("test100 arr数组");
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}
}
结论:
引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参
方法递归调用
基本介绍:
递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂问题,同时可以让代码变得简洁
递归重要规则
1执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
2方法的局部变量是独立的,不会相互受影响,比如n变量
3如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的数据
4递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死龟:)
5当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
练习
1请使用递归的方式求出斐波那契数1,1,2,3,5,8,13...给你一个整数n,求出它的值是多少。
2猴子吃桃问题:有一堆桃子,猴子第一天吃了其中一半,并在多吃了一个!以后每天猴子都吃其中的一半,然后在多吃一个。当第10天时,想再吃时(即还没吃),发现只有一个桃子了。
问:最初一共有多少个桃子?
重载
基本介绍:
java中允许同一个类中,多个同命方法的存在,但要求形参列表不一致!如:System.out.println(1.1);out是PrintStream类型
重载的好处:
1减轻了起名的麻烦
2减轻了记名的麻烦
注意事项和细节:
1方法名:必须相同
2参数列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求)
3返回类型:无需求
练习
类Methods中定义三个重在方法并调用。方法名为m。三个方法分别接受一个int参数、两个int参数、一个字符串参数。分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。在类的main()方法中分别调用参数区别调用三个方法。
class Methods{
//1方法名 m
//2新参int
//3void
public void m(int n){
System.out.println(n+"的平方="+(n*n));
}
public void m(int n1,int n2){
System.out.println(n1+"和"+n2+"相乘="+(n1*n2));
}
public void m(String str){
System.out.println("传入的str=" + str);
}
}
在Methods类,定义三个重载方法max(),第一个方法,返回两个int值中的最大值,第二个方法,返回两个double值中的最大值,第三个方法,返回三个double值中的最大值,并分别调用三个方法。
class Methods{
public int max(int n1,int n2){
return n1>n2 ? n1:n2;
}
public double max(double n1,double n2){
return n1>n2 ? n1:n2;
}
public double max(double n1,double n2,double n3){
double max1 = n1>n2 ? n1:n2;
return max1>n3 ? max1:n3;
}
}
可变参数
基本概念:
java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法
基本语法
访问修饰符 返回类型 方法名(数据类型... 形参名)
注意事项和使用细节
1可变参数的实参可以为0个或任意多个
2可变参数的实参可以为数组
3可变参数的本质就是数组
4可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
5一个形参列表中只能出雄安一个可变参数
练习:
有三个方法,分别实现返回姓名和两门课成绩(总分),返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。封装成一个可变参数的方法
class HspMethod{
public String showScore(String name,double... scores){
int sum = 0;
for(int i=0;i<scores.length;i++){
sum += scores[i];
}
return name+"的"+scores.length+"门课总成绩为"+sum;
}
}
作用域
基本使用:
1在Java编程中,主要的变量就是属性(成员变量)和局部变量
2我们说的局部变量一般是指在成员方法中定义的变量
3java中作用域的分类
全局变量:也就是属性,作用域为整个类体cat类:cry eat等方法使用属性
局部变量:也就是除了属性之外的替他变量,作用域为定义它的代码块中
4全局变量不可以赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
注意事项和细节:
1属性和局部变量可以重名,访问时遵循就近原则。
2在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名。
3属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而销毁。即在一次方法调用过程中。
4作用域范围不同
全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
局部变量:只能在本类中对应的方法中使用
5修饰符不同
全局变量/属性可以加修饰符(public protected private...)
局部变量不可以加修饰符
构造器
基本介绍:
构造方法又叫构造器,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:
1方法名和类名相同
2没有返回值
3在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化
注意事项和细节:
1一个类可以定义多个不同的构造器,即构造器重载如:我们可以再给Person类定义一个构造器,用来创建对象的时候,只指定人名,不需要指定年龄。
2构造器名和类名要相同
3构造器没有返回值
4构造器是完成对象的初始化,并不是创建对象
5在创建对象时,系统自动的调用该类的构造方法
6如果程序员没有定义构造方法,系统会自动给类生成一个默认无惨构造方法(也叫默认构造方法),比如Person(){},使用javap指令反编译看看
7一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除非显示的定义一下。即Person(){}
练习:
在person类中添加两个构造器:
第一个无参构造器:利用构造器设置所有人的age属性初始值都为18
第二个带pName和pAge两个参数的构造器:使的每次创建Person对象的同时初始化对象的age属性值和name属性值。分别使用不同的构造器,创建对象。
this
什么是this:java虚拟机会给每个对象分配this,代表当前对象。
注意事项和细节使用:
1this关键字可以用来放文本类的属性、方法、构造器
2this用于区分当前类的属性和局部变量
3访问成员方法的语句:this.方法名(参数列表);
4访问构造器语法:this(参数列表);主义只能在构造器中使用
5this不能再类定义的外部使用,只能在类定义的方法中使用
练习:
定义person类,里面有name、age属性,并提供compareTo比较方法,用于判断是否和另一个人相等,提供测试类TestPerson用于测试,名字和年龄完全一样,就返回true,否则返回false
对象创建的流程分析
1加载类信息,只会加载一次
2在堆中分配空间
3完成对象初始化
1默认初始化 age=0 name=null
2显示初始化age=90,name=null
3构造器初始化 age=20 name=小黑
4把对象在堆中的地址,赋值给p(p是对象名。也可以理解成是对象的引用)
作业:
1编写A01类,定义方法max,实现求某个double数组的最大值,并返回
2编写A02类,定义方法find,实现查找某字符串是否在数组中,并返回索引,如果找不到返回-1
3编写类Book,定义方法updatePrice,实现更改某本书的价格,具体:如果价格>150,则更改为150,如果价格>100,更改为100,否则不变
4编写类A03,实现数组的赋值功能aopyArr,输入旧数组,返回一个新数组,元素和旧数组一样
5定义一个圆类Circle,定义属性:半径,提供显示圆周长功能的方法,提供显示圆面积的方法
6创建一个Cale计算类,在其中定义2个变量表示两个操作数,定义四个方法实现求加减乘除(要求除数为0的时候,要提示)并创建两个对象,分别测试
7设计一个Dog类,有名字、颜色和年龄属性,定义输出方法show()显示其信息。并创建对象,进行测试、提示this属性
8下面程序输出结果为:10,9,10
public class Test{
int count=9;
public void count1(){
count = 10;
System.out.println("count1="+count);
}
public void count2(){
System.out.println("count1="+count++)
}
public static void main(String[] args){
new Test().count1();//匿名对象使用后,就不能再次使用了
Test().count1();
t1.count2();
t1.count2();
}
}
9定义Music类,里面有音乐名name、音乐时长times属性,并有播放play功能和返回本身属性信息的功能方法getInfo.
10下面代码的运行结果为:101,100,101,101
class Demo{
int i=100;
public void m(){
int j=i++;
System.out.println("i="+i);
System.out.println("j="+j);
}
}
class Test{
public static void main(String[] args){
Demo d1 = new Demo();
Demo d2 = d1;
d2.m();
System.out.println(d1.i);
System.out.println(d2.i);
}
}
11在测试方法中,调用method方法,写出method方法的定义形式,调用语句为:System.out.println(method(method(10.0,20.0),100));
public double method(double d1,double d2){}
12创建一个Employee类,属性有(名字、性别、年龄、职位、薪水),提供三个构造方法,可以初始化(1)(名字、性别、年龄、职位、薪水)(2)(名字、性别、年龄)(3)(职位、薪水),要求充分使用构造器
13将对象作为参数传递给方法
1定义一个Circle类,包含一个double型的radius属性代表圆的半径,一findArea()方法返回圆的面积。
2定义一个类PassObject,在类中定义一个方法printAreas(),该方法的定义如下:public void printAreas(Circle c, int times)
3在printAreas方法中打印出1到times之间的每个整数半径值,以及对应的面积。例如,times为5,则输出半径1,2,3,4,5,以及对应的圆的面积。
4在main方法中调用printAreas()方法,调用完毕后输出当前半径值。运行结果如:
Radius Area
1.0 3.1415926...
2.0 12.566370...
3.0 28.274333...
4.0 50.265482...
5.0 78.539816...
14有个人Tom设计它的成员变量.成员方法,可以电脑猜拳.电脑每次都会随机生成0,1,2。0表示石头1表示剪刀2表示布并要可以显示Tom的输赢次数(清单)

浙公网安备 33010602011771号