一、什么是面向对象
- 面向过程:线性思维
- 面对对象:分类思维
在宏观把握上使用面向对象的思路,在微观操作上使用面向过程的思路处理。
面向对象编程(Object-Oriented Programming,OOP)
- 本质:以类的方式组织代码,以对象的形式组织(封装)数据。
(对象,是具体的事物。类,是对对象的抽象) - 三大特性:封装、继承、多态。
- 抽象:具体到一般的过程。
(从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征的过程)
二、回顾方法的定义
- 修饰符
- 返回类型
- 方法名
- 参数列表
- 异常抛出
public void readFile(String file) throws IOExceotion{
}
三、回顾方法的调用
- 静态方法 static (和类一起加载)
class Student{
public static void helloWorld();
}
Student.helloWorld();
- 非静态方法 (类实例化后才存在)
class Student {
public void helloWorld();
}
Student student = new Student();
student.helloWorld();
- 形参和实参
- 值传递和引用传递
public class Demo{
Student student = new Student();
System.out.println(student.name); // null
Demo.change(student);
System.out.println(student.name); // 提莫
public static void change(Student student)
{
student.name = "提莫";
}
}
class Student {
String name;
}
- this关键字
四、类与对象的创建
- 类是一种抽象的数据类型,它是对某一类事物整体的描述或定义,但是并不能代表某一个具体的事物。
- 对象是抽象概念的具体实例。
- 使用new关键字创建对象的时候,1⃣️分配内存空间; 2⃣️默认赋值初始化;3⃣️ 调用构造器。
五、构造器(构造函数)详解
- 构造器特点:1⃣️ 必须和类的名字相同;2⃣️必须没有返回类型,也不能写void。
- 有参构造和无参构造
//无参构造的显示定义
public Person(){
}
//有参构造
public (String name){
this.name = name;
}
- 注:一旦定义了有参构造,无参构造就必须显示定义。
六、创建对象内存与分析
七、简单小结类与对象
八、封装详解
- 追求:高内聚,低耦合。
- 信息隐藏:禁止直接访问一个对象中数据的实际表示,通过操作接口来访问。
- 属性私有,通过get()/set()进行操作。
九、什么是继承 Extends
-
本质:对某一批类的抽象。
-
子类 is a 父类,子类(派生类)是父类(基类)的扩展。
-
私有的东西无法被继承。
-
在Java中,所有的类都直接或者间接继承Object类。
-
注:JAVA中类只有单继承,没有多继承。
-
接口可以多继承。
十、Super详解
this.name // 当前类
super.name // 当前类的父类
// =================
public class Person {
public Person(){
System.out.println("Person构造函数");
}
}
public class Student extends Person {
public Student(){
// 隐藏调用了父类的无参构造
// 调用父类的构造器,必须在子类构造器的第一行;
// super();
System.out.println("Student构造函数");
}
}
//=============================
Student student = new Student();
// 输出 Person构造函数
// 输出 Student构造函数
- super注意点
(1)一个构造函数中不能同时出现this和super两种方法,this方法中也包括super,会初始化两次,数据不安全。
(2)若父类中只有有参构造器,没有无参构造器,在子类无参构造中必须显示调用父类的有参构造,因为子类构造器会默认调用父类的无参构造器。
十一、方法重写
- 静态方法(不能被重写)
public class B {
pbulic static void test(){
System.out.println("B=>test()");
}
}
public class A extends B {
pbulic static void test(){
System.out.println("A=>test()");
}
}
//=============================
// 静态方法是类的方法,调用只和左边定义的数据类型有关
A a = new A();
a.test(); // A
// 父类的引用指向了子类
B b = new A();
b.test(); // B
- 非静态方法(重写)
public class B {
pbulic void test(){
System.out.println("B=>test()");
}
}
public class A extends B {
pbulic void test(){
System.out.println("A=>test()");
}
}
//=============================
// 非静态方法是对象的方法,b是用A类new的,调用的是a的方法。
A a = new A();
a.test(); // A
// 父类的引用指向了子类
B b = new A();
b.test(); // A
- 修饰符:范围可以扩大但不能缩小:public>protected>default>private
- 抛出的异常:范围可以被缩小但不能扩大:ClassNotFoundException --> Exception
十二、什么是多态
- 多态即统一方法可以根据发送对象的不同而采用不同的行为方式。
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person {
@Override
public void run(){
System.out.println("run-son");
}
public void eat(){
System.out.println("eat");
}
}
// ========================
// 一个对象的实际类型是确定的
// 可以指向的引用类型就不确定了,比如父类的引用指向子类
// Student 能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
// Person 可以指向子类,但不能调用子类独有的方法
Person s2 = new Student();
// 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s1.run(); // run-son
s2.run(); // run-son 子类重写了父类的方法,执行子类的方法
s1.eat(); // eat
s2.eat(); // 无法调用,报错
- 注意事项:
(1)执行哪个类的方法取决于右边new哪个对象;
(2)无法重写的方法:static、final、private
(3)编译看左边,运行看右边。
十三、instance of和类型转换
Object object = new Student();
// 判断某个对象是否为某个类活着任意基类的实例
// 此处的object实际是Student类的实例
System.out.println(object instanceof Student); // true
System.out.println(object instanceof Person); // true
System.out.println(object instanceof Object); // true
System.out.println(object instanceof Teacher); // False Teacher和Student同级,都是Person的子类
System.out.println(object instanceof String); // False
- 父 -> 子
Person st = new Student();
Student student = (Student) st;
- 子 -> 父 (可能丢失自己本来的一些方法)
Student student = new Student();
Person person = student;
十四、Static关键字详解
- 静态属性属于类,为所有对象(实例)所共享。
- 非静态方法可以调用静态方法,静态方法不可调用静态方法。
- 代码块
public class Person {
{
// 代码块 创建对象时自动创建,在构造器之前,赋初始值
System.out.println(“匿名代码块”);
}
static {
// 静态代码块,用于初始化,在类加载时执行
System.out.println(“静态代码块”);
}
public Person()
{
System.out.println(“构造方法”);
}
}
// ================
Person p1 = new Person();
System.out.println(“--------------”);
Person p2 = new Person();
- 输出
静态代码块
匿名代码块
构造方法
–
匿名代码块
构造方法
- 静态导入包
import static java.lang.Math.PI; // 静态导入包
- 被final修饰的类无法被继承
十五、抽象类
- abstract修饰方法,则该方法为抽象方法。
absteact修饰类,则该类为抽象类。 - 抽象类不能使用new关键字来创建对象,它是用来让子类继承的。
抽象方法只有方法的声明,没有方法的实现,它是用来让子类实现的。 - 抽象类中可以没有抽象方法,但有抽象方法的类一样要声明为抽象类。
抽象类中可以写普通方法。 - 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
- 抽象类存在构造函数。
- 抽象类就是用来实现封装,多态地增强代码的可扩展性。
十六、接口的定义与实现
- 关键字interface
- 比较
(1)普通类:只有具体实现。
(2)抽象类:具体实现和规范(抽象方法)都有。
(3)接口:只有规范,自己无法写方法。约束和实现分离 (类似于.h和.cpp) - 接口中的所有定义方法默认都是抽象的public absteact。
属性都是常量 public static final。 - 接口可以多继承。
- 接口就是规范,定义的是一组规则。
- 接口不能被实例化,没有构造方法。
- 必须要重写接口中的方法。
public interface UserService {
int AGE = 99;
void test1();
}
public interface TimeService {
void test2();
}
public class UserServiceImpl implements UserService, TimeService {
@Override
public void test1()
{
System.out.println(“接口和实现类1”);
}
@Override
public void test2()
{
System.out.println(“接口和实现类2”);
}
}
十七、N种内部类
- 成员内部类
public class Outer {
private int id = 99;
public void out() {
System.out.println(“这是外部类的方法”);
}
public class Inner {
public void out() {
System.out.println(“这是内部类的方法”);
}
// 获取外部类的私有属性
public void getID() {
System.out.println(id);
}
}
}
// =======================
Outer outer = new Outer();
// 通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID(); // 99
-
静态内部类
无法访问非静态属性。 -
局部内部类
public class Outer {
public void method() {
class Inner{
public void in()
{
System.out.println(“这是局部内部类的方法”);
}
}
}
}
- 匿名内部类
class Apple {
public void eat() {
System.out.println(“吃”);
}
}
interface UserService {
void hello();
}
// =====================
// 没有名字初始化类,不用将实例保存到变量中
new Apple().eat(); // 吃
new UserService(){
@Override
public void hello() {
}
};
- 一个源文件内只能有一个public类成员,而且必须和源文件同名。