JavaOPP小结
什么是面向对象
面向对象编程:Object-Oriented Programming,OOP
OPP本质:以类的方式组织代码,以对象的形式组织数据(封装数据)
对象的创建分析
对象的创建
类名 对象名 = new 类名();
创建对象(也叫实例化对象),我理解的是与new关键字一起使用调用了类的构造器
// 创建了一个学生对象
Student student = new Student();
类的基本结构
- 属性
- 方法
// 以学生 类 为例
// 类名(首字母大写,驼峰原则)
public class Student {
// 属性或字段
private String name;
public int age;
// 方法(即c++中的函数)
public static void study() {System.out.print("正在学习")}
public static int add(int a,int b) {return a + b;}
}
构造器
构造器(也是一种方法)即c++的构造函数
- 隐式的无参构造器
- 有参构造(注意:定义了有参构造后,必须显式定义无参构造器)
- this(类似Python里的self)指向类自身
- 创建对象,this则指向实例对象
// 学生类
public class Student(){
public String name;
// 1.无参构造
public Student(){}
// 2.有参构造
public Student(String name){
// 进行初始化
this.name = name
}
}
通过1,2分别创建对象
// 1.通过无参构造器
Student s1 = new Student(); // this指向21
// 2.通过有参构造器
Student s2 = new Student("张三"); // 这里this指向s2
子类的构造器
- 使用 父类名 对象名 = new 子类名() 创建对象会:
- 先调用Person(父类)构造器。
- 再调用Student(子类)构造器
// 部分代码示例
// 父类,Person类
public class Person extends Object{
public Person(){}
}
// 子类,Student类
public class Student extends Person{
public Student() {
super();// 隐藏代码,调用父类无参构造
}
}
- 测试代码(部分)
// 1.先调用Person(父类)构造器。
// 2.再调用Student(子类)构造器
Person p = new Student();
- 写了有参构造后,隐式的无参构造会消失(即子类无参构造无法调用 父类的无参构造),需显式写无参构造
- 若调用自己的构造器使用 this() 方法,且也必须在第一行
方法
static
static是限定属性或方法在类本身是否可以被类直接修改或调用:
- 加static:类方法
- 可通过类名调用或修改
- 可通过实例对象调用或修改
- 不加static:实例方法
- 只能通过实例对象调用或修改
public class Test(){
public static String name;
public int age;
public static void eat() {}
public void run() {}
}
- 测试代码
// 先创建对象再调用
// 属性
Test t1 = new Test();
System.out.print(t1.age)
// 方法
new Test().run();
// 通过 类名 调用
// 属性
System.out.print(Test.name)
// 方法
Test.eat();
面向对象三大特征
- 封装,继承和多态,是类的特征(为了数据安全)
- 特征通过修饰词(public,protected,default和private)来实现
- public:公有的,可被继承,可被类或对象直接访问
- protected:保护的,被继承后变为私有(private)
- default:默认的,即不加关键词的时候
- private:私有的,不可被继承,不可被对象直接访问,可使用new类名().属性调用
封装
封装:封装类的属性
- 通过公有(public)的get/set方法来间接修改或调用被封装的数据
- 一般属性是私有的,而方法是公有的
// 创建Person类
public class Person(){
// 私有属性
private String name;
private int age;
// 共有属性
public String sex;
// set方法
public void set(String name, int age){
this.name = name;
this.age = age;
}
// get方法
public void get(){
System.out.println(name);
System.out.println(age);
}
}
- 测试代码(部分)
// 创建Person实例对象
Person d = new Person();
// 属性获取
d.get(); // null 0
// 属性设置
d.set("张三",18);
// 属性获取
d.get(); // 张三 18
继承
继承:继承类的属性和方法
- 子类继承父类所有public的属性和方法。
// 部分代码示例
// 父类,Person类
public class Person extends Object{
public String name = "coline";
public eat(){
System.out.println(name + "正在吃东西");
}
}
// 子类,Student类
public class Student extends Person{
}
- 测试代码(部分)
Student s = new Student();
s.eat() // coline正在吃东西
多态
多态:基于继承通过重写同名方法实现
@Override:重写标识
- 使用 父类名 对象名 = new 子类名(); 创建对象:
Person p1 = new Student();
- 特点:
- 本质上是父类
- 可以使用父类的全部方法(没有被子类重写的全部方法)
- 可以且只能使用子类重写父类的方法(实现多态)
// 部分代码示例
// 父类,Person类
public class Person extends Object{
// run 方法,父类独有
public void breathe(){
System.out.println("Person在呼吸");
}
// eat 方法,被子类重写
public void eat(){
System.out.println("Person在吃");
}
}
// 子类,Student类
public class Student extends Person{
// run 方法,子类独有
public void run(){
System.out.println("Student跑");
}
// eat 方法,重写父类方法
@Override // 重写标识
public void eat() {
System.out.println("在吃学生餐");
}
}
- 测试代码(部分
// 通过new Person 创建Person类
Person p = new Person();
// 通过new Student 创建Person类
Person p2 = new Student();
p2.run() // 报错,Person不能调用子类 独有 方法
// 子类重写了父类方法,执行子类方法
p2.eat() // 在吃学生餐
抽象类和接口
抽象类
- 仍然是一个类
- 存在构造器~但不能直接调用
- 抽象类的子类或子类的子类必须重写抽象类的方法!!!
// 加 abstract
public abstract class Action{
// 只有方法名,没有方法的实现!
public abstract void doSomething();
// 可以有正常的方法
public void eat(){}
}
接口
关键字: interface,implements
接口不是类
// 接口
public interface UserService {
// 默认 public abstract
public abstract void add(String name);
void delete(String name);
void update(String name);
void search(String name);
}
// 接口
public interface TimeService {
// 常量 默认 public static final(可以但没必要)
int AGE = 18;
void timer();
}
// 实现类
// 利用接口实现 多继承 ~
public class UserServiceImpl implements UserService,TimeService {
// 必须实现 接口 的所有方法!!!
@Override
public void timer() {}
@Override
public void add(String name) {}
@Override
public void delete(String name) {}
@Override
public void update(String name) {}
@Override
public void search(String name) {}
}
//
-
普通类:只有具体实现
-
抽象类:具有实现和规范(抽象方法)!
-
接口:只有规范!自己无法写方法~专业的约束!约束和实现的分离:面向接口编程
N种内部类
-
成员内部类:一个项目中只能有一个public类,其他的为成员内部类
-
静态内部类:在类内部的静态的且在方法外
-
局部内部类:在方法里(主方法也算)
-
匿名内部类:没有类的名字,只有接口的名字
public class TestLambda {
//3.静态内部类
static class Like2 implements ILike{
@Override
public void lambda() {
System.out.println("this is Like2");
}
}
public static void main(String[] args) {
// (*)创建一个类型为ILike的like对象
ILike like = new Like();
like.lambda();
like = new Like2();
like.lambda();
//4.局部内部类
class Like3 implements ILike{
@Override
public void lambda() {
System.out.println("this is Like3");
}
}
like = new Like3();
like.lambda();
//5.匿名内部类
like = new ILike() {
@Override
public void lambda() {
System.out.println("this is Like4");
}
};
like.lambda();
//6.用lambda简化
//like的类型是ILike,见(*)
like = ()->{System.out.println("this is Like5");};
like.lambda();
}
}
//1.定义一个函数式接口
interface ILike{
void lambda();
}
//2.实现类(成员内部类)
class Like implements ILike{
@Override
public void lambda(){
System.out.println("this is Like");
}
}