面向对象(上)
Java面向对象学习的三条主线:(第4-6章)
- Java类及类的成员:属性、方法、构造器;代码块、内部类
- 面向对象的三大特征:封装性、继承性、多态性、(抽象性)
- 其它关键字: this.、super、static、 final、abstract 等
一、面向过程(POP)和面向对象(OOP)
- 面向过程(POP)和面向对象(OOP),二者都是一种思想,面向对象是相对于面向过程而言的。
- 面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。
- 面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
二、类的成员:
1.类的成员之一:属性
属性=成员变量= field =域、字段
①属性(成员变量)VS局部变量
a.相同点:
- 定义变量的格式:数据类型变量名=变量值
- 先声明,后使用
- 变量都有其对应的作用域
b.不同点:
- 在类中声明的位置的不同属性:成员变量直接定义在类的一对{ }内
- 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
关于权限修饰符的不同
- 成员变量:可以在声明风性时,指明其权限,使用权限修饰符。
常用的权限修饰符:private.public、缺省、protected - 局部变量:不可以使用权限修饰符
初始化值的情况:
-
成员变量:类的属性,根据其类型,都有默认初始化值。
类型 默认初始值 整型(byte、 short、 int、 long) 0 字符型(char) 0 布尔型(boolean) false 浮点型(float. double) 0.0 引用数据类型(类、数组、接口) null -
局部变量:没有默认初始化值。
意味着,我们在调用局部变量之前,一定要显式赋值。 -
特别地:形参在调用时,我们赋值即可。
返回值类型:
-
有返回值:
- 如果方法有返回值,则必须在方法声明时,指定返回值的类型,同时,方法中,需要使用 return关键字来返回指定类型的变量或常量:“return数据”。
-
没有返回值:
- 如果方法没有返回值,则方法声明时,使用void来表示。
通常,没有返回值的方法中,使用return.
但是,如果使用的话,只能“return;”表示结束此方法的意思。
- 如果方法没有返回值,则方法声明时,使用void来表示。
形参列表:
-
方法可以声明0个,1个,或多个形参。
- 格式:数据类型1 形参1,数据类型2 形参2,…
② return关键字的使用
1.使用范围:使用在方法体中
2.作用:结束方法
针对于有返回值类型的方法,使用"return数据"方法返回所要的数据。
*3.注意点:return关键字后面不可以声明执行语句。
3.类的成员之二:方法
①方法的使用
方法=成员方法=函数= method
1.方法的使用中,可以调用当前类的属性或方法
特殊的:方法A中又调用了方法A:递归方法。
2.方法中,不可以定义方法。
无返回值 | 有返回值 | |
---|---|---|
无形参 | void 方法名(){ } | 返回值的类型 方法名(){ } |
有形参 | void 方法名(形参列表 ){ } | 返回值的类型 方法名(形参列表){ } |
举例:
//无返回值的方法
public void sleep(){
}
//无返回值且带有形参的方法
public void talk(String language){
}
//有返回值的方法
public String getName(){
}
//有返回值且带有形参的方法
public int getid(int id){
}
②方法的重载
定义:在同一个类中,允许存在一个以上的同名方法,
只要它们的"参数个数"或者"参数类型"不同即可。
“两同一不同”:同一个类、同一个方法名
参数不同 (个数、类型等)
//举例:
//方法的重载
public void getSum(int i, int j){
}
public void getSum(String a,String b){
}
例题:
package text;
public class friend {
//1.编写程序,定义三个重载方法并调用。方法名为mOL。
// 三个方法分别接收一个int参数、两个int参数、一个字符串参数。
// 分别执行平方运算并输出结果,相乘并输出结果,输出字符串信息。
// 在主类的main ()方法中分别用参数区别调用三个方法。
public void mol(int i){
System.out.println(i*i);
}
public void mol(int i,int j){
System.out.println(i*j);
}
public void mol(String a){
System.out.println(a);
}
// 2.定义三个重载方法max(),
// 第一个方法求两个int值中的最大值,
// 第二个方法求两个double值中的最大值,
// 第三个方法求三个double值中的最大值,
// 并分别调用三个方法。
public void max(int i,int j){
if(i>j){
System.out.println(i);
}else{
System.out.println(j);
}
}
public void max(double i,double j){
if(i>j){
System.out.println(i);
}else{
System.out.println(j);
}
}
public void max(double i,double j,double k){
if(i>j&&i>k){
System.out.println(i);
}else if(j>i&&j>k){
System.out.println(j);
}else{
System.out.println(k);
}
}
}
package text;
public class friendtext {
public static void main(String[]args){
// friendtext text=new friendtext();
friend f=new friend();
f.max(10,12);
f.max(10.0,12.0);
f.max(10.0,12.0,13.0);
f.mol(10);
f.mol("tom");
f.mol(10,12);
}
}
③可变形参的方法
1.可变个数形参的格式: 数据类型…变量名
2.当调用可变个数形参的方法时,传入的参数个数可以是: 0个,1个,2个…
3.可变个数形参的方法与本类中方法名相同,形参不同的方法之间构成重载
4.可变个数形参的方法与本类中方法名相同,形参类型也相同的"数组"之间不构成重载。
换句话说:两者之间不能同时出现。
5.可变个数形参在方法的形参中,必须声明在末尾
6.可变个数形参在方法的形参中,最多只能声明一个可变形参。
package text;
import java.util.Arrays;
public class friend {
//可变形参的方法
public void mol(String a){
System.out.println(a);
}
public void mol(String a,String b){
System.out.println(a+" "+b);
}
//public void mol(String[]str){
//
//}
//注意这里其实和上面的数组系统会认定为"一模一样"
public void mol(String ... str){
System.out.println("目前已进入mol(String ... str);方法");
//输出写法一:
for(int i=0;i<str.length;i++){
System.out.print(str[i]+" ");
}
System.out.println(" ");
//输出写法二:
System.out.println( Arrays.toString(str));
// 错误写法: Arrays.toString(str);
// 正确写法:
Arrays.toString(str);
System.out.println( Arrays.toString(str));
}
}
package text;
public class friendtext {
public static void main(String[] args) {
friend f=new friend();
f.mol("tom");
f.mol("tom","jennry");
f.mol("tom","jennry","Lily");
}
}
④方法参数的值传递机制
a.形参和实参的定义
形参:方法定义时,声明的小括号内的参数
实参:方法调用时,实际传递给形参的数据
b.变量的赋值:
如果变量是 基本数据类型,此时赋值的是变量所保存的 数据值。
如果变量是 引用数据类型,此时赋值的是变量所保存的数据的 地址值。
c. 值传递机制
如果参数是基本数据类型,此时实参赋给形参的是实参真实存储的数据值。
如果参数是引用数据类型,此时实参赋给形参的是实参存储数据的地址值。
例题:
数组排序
package text;
import java.util.Arrays;
public class arrtext {
public static void main(String[] args) {
int[] arr1 = new int[]{
9,45,1,56,89,29,21,2,34,8};
System.out.println(Arrays.toString(arr1)+" ");
arrtext a=new arrtext();
//冒泡排序
for(int j=0;j<arr1.length-1;j++){
for(int i=0;i<arr1.length-1-j;i++){
if(arr1[i+1]<arr1[i]){
//注意这里的参数(arr1,i,i+1)——正确写法
a.swap(arr1,i,i+1);
}
}
}
//Arrays 工具类进行数组输出
Arrays.toString(arr1);
System.out.print(Arrays.toString(arr1)+" ");
}
//注意这里的形参(int arr1[],int i,int j)——正确写法
public void swap(int arr1[],int i,int j){
int temp=arr1[i];
arr1[i]=arr1[j];
arr1[j]=temp;
}
}
圆的面积计算
//从键盘上获取数字
Scanner scanner =new Scanner(System.in);
scanner.nextInt();
package text;
public class circle {
// 定义一个Circle类,包含一个double型的radius属性代表圆的半径
// 一个findArea()方法返回圆的面积。
double radious; //圆的半径
public void finfArea(){
double s=Math.PI*radious*radious;
System.out.println(s);
}
}
public class arrtext {
public static void main(String[] args) {
//
// 定义一个类Passoject,在类中定义一个方法printAreas (),
// 该方法的定义如下public void printAreas (Circle c,int time)
// 在printAreas方法中打印输出1到time之间的每个整数半径值,以及对应的面积
// 例如,times为5,则输出半径1,2,3,4,5,以及对应的圆面积。
circle c=new circle();
arrtext a=new arrtext();
System.out.println("输入你想要的时间:");
Scanner scanner =new Scanner(System.in);
int s=scanner.nextInt();
a.arrtextArea(c,s);
}
public void arrtextArea(circle c, int time){
//输出的半径
for(int i=time;i>0;i--){
System.out.print(i+" ");
c.radious=i;
c.finfArea();
}
}
}
⑤递归方法
1.递归方法:一个方法体内调用它自身。
2.方法递归包含了一种隐式的循环,它会重复执行某段代码,但这种重复执行无须循环控制。 递归一定要向已知方向递归,否则这种递归就变成了无穷递归,类似于死循环。
package text;
import java.util.Arrays;
import java.util.Scanner;
public class arrtext {
public static void main(String[] args) {
// 求100以内的数字之和
arrtext a=new arrtext();
System.out.println("输入你要的数字————求100以内的数字和");
Scanner scanner=new Scanner(System.in);
int c=scanner.nextInt();
a.sum(c);
}
public int sum(int i){
if(i==1){
System.out.println("只有数字1");
return 1;
}else{
int s= i+sum(i-1);
System.out.println("前"+i+"项数字的和为"+s);
return s;
}
}
}
⑤方法的重写
a.重写:
子类继承父类以后,可以对父类中同名同参数的方法,进行“覆盖”操作
b.应用:
重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法
c.重写的规定
-
方法的声明:权限修饰符返回值类型方法名(形参列表) throws异常的类型{//方法体 }
约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法-
子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同,
-
子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
特殊情况:子类不能重写父类中声明为private权限的方法返回值类型:
-
-
举例:
-
父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
-
父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
-
父类被重写的方法的返回值类型是基本数据类型(比如: double),则子类重写的方法的返回值类型必须是相同的数据类型(double)
-
子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
注意:子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不属于重写)。
-
d.例题:
//修改练习定义的类Kids,在Kids中重新定义employeed()方法,
// 覆盖父类Mankind中定义的employeed()方法,
// 输出"Kids should study and no job."
package text3;
public class Mankind {
// *定义一个ManKind类,包括
// 成员变量int sex和int salary;
// 方法void manorwoman( ):根据sex的值显示"