面向对象阶段
什么是类?
**类:**具有相同属性和行为的集合,是一个抽象的概念,不指向具体的事务。
- 属性:描述对象的特征,在程序中,体现为成员变量;
- 行为:对象的动作或者状态,在程序中,体现为方法。
什么是对象?
**对象:**类是对象的一个具体实例,是事务的具体体现。
- 创建对象:
类名 对象名 = new 类名([参数]); - 读写属性:
对象名.属性名 - 调用方法:
对象名.方法名([参数]);
类与对象的关系
类是对象的集合;对象是类的具体实例。从类到对象的过程就是类的实例化。
成员变量
- 成员变量是指在类中定义的变量,分为类变量(使用static修饰)和实例变量(不使用static修饰);
- 实例变量随实例的创建产生,当实例被销毁时,实例变量也会跟着被销毁;而类变量的作用范围在类的整个生存期间都有效;
- 成员变量的作用域是整个类;
- 类变量也可以用类的实例来访问。
局部变量
- 定义在方法中的变量称为局部变量;
- 除形式参数外,局部变量都没有默认值,在定义时必须初始化;
- 局部变量的作用域在它所在的大括号内,当方法执行完成后,局部变量就会消失。
成员变量与局部变量的区别:
- 成员变量是类的一部分,随类或实例的创建而存在;而局部变量随着方法的调用自动消失;
- 成员变量可以不赋初始值,会自动以类型的默认值赋初始值(被final修饰的成员变量需要在定义的时候赋初始值);而局部变量必须要在使用前给定义的变量赋值。
面向对象的三大特征
封装
使用private修饰符对属性进行修饰,限制属性的访问权限,只有内部能够访问这样的属性,其他的类通过 对象.属性 的方式是无法访问的。从而对对象的状态(数据)进行保护,外部需要访问的话需要通过get/set的方法,保证属性统一访问。
- 创建一个学生类Student
提供get,set方法访问属性。在set时可以限制赋值的内容;在get时可以返回指定格式的数据,转换和限制逻辑封装在类中的方法中。
package com.hqyj;
public class Student {
//private 私有修饰符
private String name;
private int sex;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
String result = sex == 1 ? "男" : " 女";
return result;
}
public void setSex(int sex) {
if (sex < 0 || sex >1){
throw new RuntimeException("性别只能是0和1!");
}
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
- 使用学生类
使用学生类是不能直接访问属性,必须通过get,set方法。
如果给属性赋值,不符合要求,就会报异常。
用get方法读取属性,就会读取到学生类中转换后的内容(比如这里的男,女)
package com.hqyj;
public class StudentTest {
public static void main(String[] args) {
Student student = new Student();
//student.name = "李四";//私有成员变量,不能直接访问
student.setName("小李");//私有属性只能通过set/get方法访问
student.setAge(22);
student.setSex(1);
System.out.println(student.getSex());
}
}
继承
A类通过extends关键字继承B类,集成之后A类就可以有B类中的属性和方法,实现代码的重复利用。
- 继承的特点
- 继承只能是单继承,即只能有一个父类;但是一个父类可以有多个子类;
- 继承可以是多重的继承,A继承B,B继承C;
- Object是所有类的父类(所有类都继承至Object);
- 子类可以重写(覆盖)父类的方法;
- 创建子类时,会先执行父类的构造方法。
**重写(override):**子类继承父类时,子类对父类的方法代码重新写过,就叫重写。
**重载(overload):**在一个类中(不一定要继承)中,如果有多个方法的方法名相同,参数列表不同(个数,类型,顺序),这些同名的方法就称为重载。
this关键字和super关键字
-
这两个关键字都可以指代对象或方法。
-
在子类中,当子类和父类方法重名,优先调用子类的方法,如果要调用父类的方法,要用super关键字去访问。
-
当成构造方法使用
- 构造方法中调用构造方法,用this代替构造方法名;
- 构造方法中调用构造方法,调用语句只能放在第一行;
- 子类要调用父类的构造方法,用super();
- 如果子类的构造方法没有调用父类的构造方法,默认会调用父类的无参构造方法;
- 如果父类没有无参构造方法,在子类的构造方法中必须要调用父类的有参的构造方法。
- 理解this和super
- this:代表当前的对象,谁调用就代表谁,访问的是本类中的属性,本类中没有则从父类中继续查找;
- super:当子类和父类的方法重名时,会优先调用子类的方法,如果想要调用父类的方法,需要使用super关键字来调用,super代表的是当前对象对父类的引用,访问的是父类中的属性;
- this()和super()不能存在于同一个构造函数中;
- this和super指的都是对象(实例),所以都不能用于static修饰的变量;
- this和super在构造函数中都必须写在第一行。
多态
在类中在编译和运行时同一个方法呈现出不同的状态就叫多态。
- 形成多态的条件:
- 有继承关系,有多个子类,子类重写父类的方法;
- 父类类型定义的变量,用子类的实例给它赋。
多态的用处: 统一管理,无限适配或扩展。
例如:Windows操作系统有打印功能,规定好打印方法,不同类型的打印机(针式,喷墨,激光,黑白,彩色…)只要继承重写打印方法,就可以实现自动适配所有的打印机。
- Animal.java
public class Animal {
public void shout(){
System.out.println("动物在叫");
}
}
- Cat.java
public class Cat extends Animal{
@Override
public void shout() {
System.out.println("喵喵喵");
}
public void eat(){
System.out.println("猫吃鱼");
}
}
Dog.java
public class Dog extends Animal{
@Override
public void shout() {
super.shout("汪汪汪");
}
public void eat(){
System.out.println("狗吃骨头");
}
}
- 测试代码AnimalTest.java
public class AnimalTest {
public static void main(String[] args) {
Animal animal1 = new Animal();
animal1.shout();
Cat cat = new Cat();
cat.shout();
Dog dog = new Dog();
dog.shout();
System.out.println("==========Animal animalCat = cat;==========");
Animal animalCat = cat;
animalCat.shout();//喵喵喵
System.out.println("==========Animal animalDog = dog;==========");
Animal animalDog = dog;
animalDog.shout();//汪汪汪*/
}
}
内部类
定义在类中的类称为内部类。
作用:封装:一般自己使用的不想让别人使用的类定义为内部类。
成员内部类(内部类定义在大括号里)
- 内部类定义为一个成员(跟成员变量或方法同一级);
- 内部类可以用任意访问修饰符(一般要起封装作用要用private);
- 内部类可以访问外部类的属性和方法;外部类不能直接访问内部类的属性和方法,只能通过对象去访问;
- 内部类的对象初始化要借助外部类的对象才能够初始化:Outer.Inner inner = outer.new Inner();
package com.hqyj;
public class Outer {
private String id = "abcd123";
private void funOuter(){
System.out.println("外部类的方法funOuter");
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.funOuter();
//Inner inner = outer.new Inner();可以写成Outer.Inner inner = outer.new Inner();
Inner inner = outer.new Inner();
inner.funInner();
System.out.println(inner.name);
}
private class Inner{
public Inner(){
System.out.println("Inner的构造方法");
}
private String name = "innerclass";
public void funInner(){
System.out.println(id);
System