面向对象
一、类与对象
1.现实中
对象 :对象是类的一个实例(对象不是找个女朋友 ),有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
类 :类是一个模板,它描述一类对象的行为和状态。
下图中男孩(boy) 、女孩(girl) 为类(class) ,而具体的每个人为该类的对象(object) :
下图中汽车 为类(class) ,而具体的每辆车为该汽车 类的对象(object) ,对象包含了汽车的颜色、品牌、名称等。
2.Java中
类可以看成是创建 Java 对象的模板。
一个类可以包含以下类型变量:
局部变量 :在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。
成员变量 :成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。
类变量 :类变量也声明在类中,方法体之外,但必须声明为 static 类型。
一个类可以拥有多个方法,在上面的例子中:eat()、run()、sleep() 和 name() 都是 Dog 类的方法。
语法:
1 2 3 4 5 6 7 8 9 public class 类名 { }
注意:类中的属性不再书写static,后续详解。
案例1:类的定义
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Dog { String breed; int age; String sex; String furColor; public void eat () { System.out.println("eat..." ); } public void sleep () { System.out.println("sleeping..." ); } }
案例2:对象的创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class TestCreateObject { public static void main (String[] args) { Dog myDog = new Dog(); myDog.breed = "萨摩" ; myDog.age = 2 ; myDog.sex = "公" ; myDog.furColor = "白色" ; System.out.println(myDog.breed + " " + myDog.age + " " + myDog.sex + " " + myDog.furColor);; myDog.eat(); myDog.sleep(); } }
运行结果:
3.类与对象的关系
类:定义了对象应具有的特征和行为,类是对象的模板。
对象:拥有多个特征和行为的实体,对象是类的实例。
二、实例变量
思考:之前的局部变量,要求必须赋值后在使用,否则编译错误,对于实例变量而言,未赋值能直接访问吗?
1 2 3 4 5 6 public class TestCreateObject { public static void main (String[] args) { Dog myDog = new Dog(); System.out.println(myDog.breed + " " + myDog.age + " " + myDog.sex + " " + myDog.furColor);; } }
运行结果:
可以直接访问,具有默认值。
实例变量的默认值:
1 2 3 4 5 整数:0 小数:0.0 字符:\u0000 空格 布尔:false 其他:null
实例变量与局部变量的区别
局部变量
实例变量
定义位置
方法或方法内的结构中
类的内部,方法的外部
默认值
无默认值
有默认值
使用范围
从定义行到包含其结构结束
本类有效
命名冲突
不允许与局部变量重名
不允许与实例变量重名,可与局部变量重名,局部变量优先。
三、实例方法
对象的实例方法包含两部分:方法的声明和方法的实现。
方法的声明:
代表对象能做什么
组成:修饰符 返回值类型 方法名(形参列表)
方法的实现:
代表对象怎么做:即如何实现对应功能
组成:{ 逻辑代码 }
上面中定义的Dog
类中的eat
是实例方法。
1 2 3 4 5 6 public class Dog { public void eat () { System.out.println("eat..." ); } }
案例1:
定义学生类,包含属性姓名(name)、年龄(age)、性别(sex)、分数(score);包含方法打招呼(sayHi),打印学生所有信息。并创建多个学生对象,为其各个属性赋值,并调用方法。
Student.java
1 2 3 4 5 6 7 8 9 10 public class Student { String name; int age; String sex; double score; public void sayHi () { System.out.println("大家好,我是" +name+" 年龄" +age+" 性别" +sex+" 分数" +score); } }
TestStudent.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class TestStudent { public static void main (String[] args) { Student xiaoming = new Student(); xiaoming.name = "小明" ; xiaoming.age = 18 ; xiaoming.sex = "男" ; xiaoming.score = 98 ; xiaoming.sayHi(); Student xiaoli = new Student(); xiaoli.name = "小李" ; xiaoli.age = 20 ; xiaoli.sex = "男" ; xiaoli.score = 95 ; xiaoli.sayHi(); } }
运行结果:
案例2:
创建一个老师类Teacher,包含属性姓名(name)、年龄(age)、工资(salary),方法打招呼sayHi,认识学生know。
Teacher.java
1 2 3 4 5 6 7 8 9 10 11 12 public class Teacher { String name; int age; double salary; public void sayHi () { System.out.println("大家好!我是" +name+"老师,今年" +age+"岁。" ); } public void know (Student stu) { System.out.println("认识了学生" +stu.name); } }
TestTeacher.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class TestTeacher { public static void main (String[] args) { Teacher wang = new Teacher(); wang.name = "王老师" ; wang.age = 32 ; wang.salary = 30000 ; Student xiaoming = new Student(); xiaoming.name = "小明" ; xiaoming.age = 18 ; xiaoming.sex = "男" ; xiaoming.score = 98 ; wang.sayHi(); wang.know(xiaoming); } }
运行结果:
四、方法重载
有些情况下,对象的同一种行为可能存在多种实现过程,例如,人的”吃“行为,吃饭和吃药都是吃,但是吃的物质和过程存在差异,所以到底采用哪种实现过程取决于调用者给定的参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Person { public void eat (食物 a) { } public void eat (药物 b) { } public void eat (口香糖 c) { } }
重载(overload):一个类定义多个相同名称的方法。
要求:
方法名称相同
参数列表不同(类型、个数、顺序)
与访问修饰符、返回值类型无关
调用带有重载的方法时,需要根据传入的实参去找到与之匹配的方法。
好处:灵活、方便、屏蔽使用差异
案例1:
在Operation
类中定义重载方法。
Operation.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Operation { public void show () { System.out.println("这是一个无参的方法" ); } public void show (int a) { System.out.println("这是一个带int参数的方法" ); } public void show (String s) { System.out.println("这是一个带String参数的方法" ); } public void show (int a,String s) { System.out.println("这是一个带int String参数的方法" ); } public void show (String s,int a) { System.out.println("这是一个带String int参数的方法" ); } }
TestOperation.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class TestOperation { public static void main (String[] args) { Operation oper = new Operation(); oper.show(); oper.show(100 ); oper.show("hello" ); oper.show(200 ,"hello" ); oper.show("hello" ,300 ); } }
运行结果:
思考:以下方法是不是重载?
1 2 public void m (int a) {}public void m (int b) {}
上面两个方法的方法名称和参数列表都相同,只有参数名称不一样,不满足方法重载的条件,编译报错。
注意:只是参数名称不同,并不能构成方法的重载。
五、构造方法
类中的特殊方法,主要用于创建对象。
特点:
名称与类名完全相同
没有返回值类型
创建对象时,触发构造方法的调用,不能通过手动句点调用
注意:如果没有在类中手动定义任何构造方法,编译器则默认提供无参构造方法
案例1:
Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Student { String name; int age; String sex; double score; public Student () { System.out.println("无参构造方法" ); name = "hhhh" ; age = 18 ; sex = "男" ; } public void sayHi () { System.out.println("大家好,我是" +name+" 年龄" +age+" 性别" +sex+" 分数" +score); } }
TestStructure.java
1 2 3 4 5 6 7 public class TestStructure { public static void main (String[] args) { Student stu = new Student(); stu.sayHi(); } }
运行结果:
创建对象的时候,调用无参构造方法,给对象属性赋值。而score
未赋值,所以为0.0
对象创建过程的内存分配,Student stu
此时再堆中创建了一个Student类型的stu变量,这时变量没有值,当new Student()时,首先在栈中开辟了对象空间,为各个属性赋予初始值,然后在执行构造方法中的代码,然后将开辟的对象空间的引用给堆中的stu变量。
因为构造方法中没有给score赋值,所以score的默认值0.0
构造方法的重载
构造方法也可重载,遵循重载规则,与普通方法类似。
案例2:
Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class Student { String name; int age; String sex; double score; public Student () { System.out.println("无参构造方法" ); } public Student (String name1,int age1) { System.out.println("带String int参数的构造方法" ); name = name1; age = age1; } public Student (int age1,String name1) { System.out.println("带int String参数的构造方法" ); age = age1; name = name1; } public Student (String name1,int age1,String sex1) { System.out.println("带String int String参数的构造方法" ); name = name1; age = age1; sex = sex1; } public void sayHi () { System.out.println("大家好,我是" +name+" 年龄" +age+" 性别" +sex+" 分数" +score); } }
TestStructure.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class TestStructure { public static void main (String[] args) { Student stu = new Student(); stu.sayHi(); stu = new Student("xiaoming" ,18 ); stu.sayHi(); stu = new Student(19 ,"xiaohong" ); stu.sayHi(); stu = new Student("zhangsan" ,22 ,"男" ); stu.sayHi(); } }
运行结果:
默认构造方法
如果类中定义了构造方法,则编译器不提供默认的无参构造方法,如果此时没有定义无参构造方法,当调用时会报错。
案例3:
Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Student { String name; int age; String sex; double score; public Student (String name1) { System.out.println("带String参数的构造方法" ); name = name1; } public void sayHi () { System.out.println("大家好,我是" +name+" 年龄" +age+" 性别" +sex+" 分数" +score); } }
TestStructure.java
1 2 3 4 5 6 7 8 9 10 public class TestStructure { public static void main (String[] args) { Student stu = new Student("xiaoming" ); stu.sayHi(); Student stu1 = new Student(); stu1.sayHi(); } }
运行结果:
六、this关键字
类是模板,可服务于此类的所有对象,this是类中的默认引用,代表当前实例 ;当类服务于某个对象时,this则指向这个对象。
案例1:this的第一种用法 ,调用实例属性,实例方法
调用实例属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public Student (String name1,int age1,String sex1) { System.out.println("带String int String参数的构造方法" ); name = name1; age = age1; sex = sex1; } public Student (String name,int age,String sex) { System.out.println("带String int String参数的构造方法" ); this .name = name; this .age = age; this .sex = sex; }
调用实例方法
Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Student { String name; int age; String sex; double score; public Student () { System.out.println("无参构造方法" ); } public Student (String name,int age,String sex) { System.out.println("带String int String参数的构造方法" ); this .name = name; this .age = age; this .sex = sex; } public void sayHi () { System.out.println("大家好,我是" +name+" 年龄" +age+" 性别" +sex+" 分数" +score); } public void eat () { System.out.println("吃" ); this .sayHi(); } }
TestThis.java
1 2 3 4 5 6 public class TestThis { public static void main (String[] args) { Student stu = new Student("xiaoming" ,18 ,"男" ); stu.eat(); } }
运行结果:
案例2:this的第二种用法,调用本类中其他构造方法
在构造方法中,调用本类的其它构造方法,即可复用构造方法中的逻辑代码。
注意:通过this调用本类中其它构造方法,这条语句必须在构造方法的首行,且只能有一条。
Student.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Student { String name; int age; String sex; double score; public Student () { System.out.println("无参构造方法" ); } public Student (String name, int age, String sex) { System.out.println("带String int String参数的构造方法" ); this .name = name; this .age = age; this .sex = sex; } public Student (String name, int age, String sex,double score) { this (name,age,sex); System.out.println("带String int String double参数的构造方法" ); this .score = score; } public void sayHi () { System.out.println("大家好,我是" +name+" 年龄" +age+" 性别" +sex+" 分数" +score); } }
TestThis.java
1 2 3 4 5 6 public class TestThis { public static void main (String[] args) { Student stu = new Student("xiaoming" ,18 ,"男" ,98.0 ); stu.sayHi(); } }
运行结果: