面向对象编程
一、概念
- 面向过程:步骤清晰简单,第一步做什么,第二步做什么…适合处理简单的问题
- 面向对象:分类的思维模式。适合处理复杂的问题,合适处理需要多人协助的问题
- 面向对象编程(OOP):以类的方式组织代码,以对象的形式封装数据!
- 三大特性:封装、继承、多态
- 面向对象编程(OOP):以类的方式组织代码,以对象的形式封装数据!
二、类与对象的创建
- 类:是一种抽象的数据类型,它是对某一类事物整体描述/定义,不能代表具体的某一个事物
- 对象:是抽象概念的具体实例
//类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name);//this是实例对象本身
}
}
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//类实例化,会返回一个自己的对象
Student student = new Student();
System.out.println(student.name);
}
}
三、构造器
-
特点
- 1:必须和类名字相同
- 2:必须没有返回类型,也不能写void
-
作用
-
1、使用new实例化,本质是在调用构造器。(.class文件打开可以看到默认有个构造器,若自己定义构造器则方法重载)
public class Person { public Person() { } }
-
2、用于实例化初始值
- 无参构造器
- idea快捷键:alt+insert(部分笔记本的alt+fn+insert),选择constructor,选择select None
public class Person { String name; //无参构造器 public Person(){ this.name = "无参构造器"; } }
public class Application { public static void main(String[] args) { //new无参构造器 Person person = new Person(); System.out.println(person.name); } }
- 有参构造器
- idea快捷键:alt+insert(部分笔记本的alt+fn+insert),选择constructor,选择OK
public class Person { String name; //有参构造器 public Person(String name){ this.name = name; } }
public class Application { public static void main(String[] args) { //new有参构造器 Person person = new Person("有参构造器"); System.out.println(person.name); } }
- 无参构造器
-
四、三大特性—封装
-
作用
- 提高程序安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 增加系统可维护性
-
高内聚,低耦合!
-
属性私有,需要提供方法:get(获取数据)/set(设置数据)!
- idea快捷键:alt+insert(部分笔记本的alt+fn+insert),选择Getter and Setter,选择OK
public class Student { //privite属性私有,外部无法直接使用 private String name; //提供get方法 public String getName(){ return this.name; } //提供set方法,可以在方法内做数据校验 public void setName(String name){ if (name.isEmpty()){ this.name = "空字符串"; }else { this.name = name; } } }
public class Application { public static void main(String[] args) { Student student = new Student(); System.out.println(student.getName()); //null student.setName("set方法"); System.out.println(student.getName()); //set方法 }}
五、三大特性—继承
1、基础
- java中只有单继承,没有多继承(一个父类可以有多个子类,但一个子类只能有一个父类)
- java中所有类,都默认继承object类
- 父类(基类)、子类(派生类,extends)。子类是父类的扩展。
- 私有的属性和方法无法被继承
//父类public class Father { //父类的方法 public void fatherMethod(){ System.out.println("父类的方法"); }}
//Son类继承Father类(派生类)public class Son extends Father{ //按ctrl+H可以显示树}
public class Application { public static void main(String[] args) { Son son = new Son(); //子类拥有父类的方法 son.fatherMethod(); }}
2、super
-
this:调用自身类的属性和方法(不需要继承)
- 调用子类构造器this(),代码必须放在第一行
-
super:调用父类的属性和方法(必须继承)
- 调用父类构造器super(),代码必须放在第一行
- super只能出现在子类的方法或者构造器中
- super() 和 this() 不能同时使用,因为都要放在第一行,否则会报错
//父类public class Father { protected String name = "父类的name"; public void print(){ System.out.println("父类的print()"); }}
//Son类继承Father类(派生类)public class Son extends Father{ private String name = "子类的name"; //属性调用测试 public void test1(String name){ System.out.println(name); //传参的 System.out.println(this.name); //this:子类的 System.out.println(super.name); //super:父类的 } public void print(){ System.out.println("自身类的print()"); } //方法调用测试 public void test2(){ print(); //自身类的 this.print(); //自身类的 super.print(); //父类的 }}
3、方法重写
- 父类的引用指向子类
//父类public class Father { public static void test(){ System.out.println("父类的test()"); }}
//Son类继承Father类(派生类)public class Son extends Father{ public static void test(){ System.out.println("子类的test()"); }}
public class Application { public static void main(String[] args) { Son son = new Son(); son.test(); //子类的 //父类的引用指向子类!!! Father father = new Son(); father.test(); //父类的 }}
-
@Override方法重写
- idea快捷键1:alt+insert(部分笔记本的alt+fn+insert),选择Override Methods,选择要重写的方法,选择OK
- idea快捷键2:ctrl+O选择要重写的方法,选择OK
- 父类的功能子类不全需要或部分不满足时,需要重写方法
- 需要满足的条件
- 方法名必须相同
- 参数列表必须相同(若不同,则变成重载)
- 修饰符范围可以扩大,不能缩小(public>protected>default>private )
- 抛出的异常范围可以被缩小,但不能扩大(classNotFoundException<Exception)
//父类public class Father { public void test(){ System.out.println("父类的test()"); }}
//Son类继承Father类(派生类)public class Son extends Father{ @Override public void test() { //super.test(); //默认是调用父类的 System.out.println("子类重写父类的方法"); }}
public class Application { public static void main(String[] args) { Son son = new Son(); son.test(); //子类的 //父类的引用指向子类 Father father = new Son(); //子类重写父类的方法 father.test(); }}
六、三大特性—多态
1、基础
(参考方法重写章节)
-
同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用类型有很多
-
注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类有联系。注意类型转换异常:classcastException
- 存在条件:继承、方法重写,父类引用指向子类对象
public class Application { public static void main(String[] args) { //多态 Son son = new Son(); Father father = new Son(); Object object = new Son(); }}
2、instanceof和类型转换
-
instanceof:判断是否存在父子关系
- 格式:x instanceof y
-
类型转换(父类引用指向子类对象)
- 子类转换为父类,向上转换
- 父类转换为子类,向下转换,强制转换
//父类public class Father { public void testFather(){ System.out.println("父类的testFather()"); }}
//Son类继承Father类(派生类)public class Son extends Father{ public void testSon(){ System.out.println("子类的testSont()"); }}
public class Application { public static void main(String[] args) { Object object = new Son(); //======判断是否存在父子关系 System.out.println(object instanceof Son); //true System.out.println(object instanceof Father);//true System.out.println(object instanceof Object);//true System.out.println(object instanceof String);//false //======类型转换 //高--------------低 Father father = new Son(); //Father中没有testSon()方法,无法直接调用,会报错 //father.testSon(); //强制转换类型后可以调用 ((Son)father).testSon(); }}
3、static修饰符
-
静态/非静态变量
public class Demo1 { private static int age1; //静态变量 private int age2; //非静态变量 public static void main(String[] args) { //类名.变量(静态变量) System.out.println(Demo1.age1); //System.out.println(Demo1.age2);//非静态变量,无法通过这种方式获取 //实例化对象.变量(静态/非静态变量) Demo1 demo1 = new Demo1(); System.out.println(demo1.age1); System.out.println(demo1.age2); }}
-
静态/非静态方法
public class Demo1 { //静态方法 public static void run1(){} //非静态方法 public void run2(){} public static void main(String[] args) { //静态方法可以直接调用 run1(); //非静态方法无法直接调用,需要实例化 Demo1 demo1 = new Demo1(); demo1.run2(); }}
-
静态/非静态代码块
public class Demo1 { { System.out.println("匿名代码块"); } static { //只会执行一次 System.out.println("静态代码块"); } public Demo1() { System.out.println("构造方法"); } public static void main(String[] args) { /*输出 静态代码块 匿名代码块 构造方法 */ Demo1 demo1 = new Demo1(); System.out.println("=============="); /*输出 匿名代码块 构造方法 */ Demo1 demo2 = new Demo1(); }}
-
静态导入包
import static java.lang.Math.random;public class Demo1 { public static void main(String[] args) { System.out.println(Math.random()); //没有静态导入包 System.out.println(random()); //静态导入包后 }}
4、abstract抽象类、方法
抽象类是为了提高代码开发效率。
-
不能new抽象类,只能靠子类来实现,相当于是个约束
-
抽象类里也可以有普通方法
-
抽象方法必须在抽象类下
//父类,抽象类public abstract class Father { //抽象方法,只有方法名字,没有方法实现,由子类来实现 public abstract void doSomething();}
//子类,若父类是抽象类,子类必须重写父类的抽象方法,除非该子类也是抽象类public class Son extends Father{ @Override public void doSomething() { }}
5、interface接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范都有
-
接口:
- 约束;只有规范,接口的本质是契约。约束和实现分离:面向接口编程
- 定义一些方法,让不同的人实现
- 不能new接口,接口中没有构造方法
- implements可以实现多个接口
//接口,都需要有实现类public interface UserService { //接口中的所有定义都是抽象的 void add();}
public interface MoreService { void delete();}
//接口实现类,需要重写接口中的方法。可以实现多个public class UserServiceImpl implements UserService,MoreService{ @Override public void add() { } @Override public void delete() { }}
6、内部类
-
成员内部类
//外部类public class Out { private int id = 10; public void out(){ System.out.println("外部类的方法"); } //成员内部类 class Inner{ public void in(){ System.out.println("内部类的方法"); } //获取外部类的私有属性 public void getID(){ System.out.println(id); } }}
public class Application { public static void main(String[] args) { //实例化外部类 Out out = new Out(); //通过外部类来实例化内部类 Out.Inner inner = out.new Inner(); }}
-
静态内部类
//外部类public class Out { private int id = 10; public void out(){ System.out.println("外部类的方法"); } //静态内部类 class static Inner{ public void in(){ System.out.println("内部类的方法"); } //获取外部类的私有属性 public void getID(){ System.out.println(id); } }}
-
局部内部类
//外部类public class Out { public void method(){ //局部内部类,写在方法里面 class local{} }}
-
匿名内部类
//外部类public class Out { public void method(){ } public static void main(String[] args) { //匿名内部类:没有名字的初始化类,不用将实例保存到变量中 new Out().method(); }}