一、什么是面向对象
面向过程:线性思维
面向对象:以类的方式组织代码,以对象的方式组织数据
- 同一个包指同一层级,即同一目录层级下
- 子类和父类在同一包下,子类可使用除private外的父类成员;
- 子类和父类不在同一包下,子类只能使用protected和public的父类成员
二、回顾方法
2.1 方法的定义
- 修饰符
- 返回类型
- break:(跳出switch,结束循环)和return(结束方法,返回结果)区别
- 方法名:注意规范、见名知意
- 参数列表:参数类型、参数名,可变长参数
- 异常抛出:后面讲解
2.2 方法的调用
- 静态方法(可通过类调用)和非静态方法(只能通过实例调用),static
- 形参和实参
- 值传递和引用传递
- this关键字:代表类的实例,和python中的self类似,this可以提高程序可读性,不写不影响代码执行;this指向实例自身
- this.什么时候不能省略:用来区分局部变量和实例变量的时候,不能省
三、类与对象的创建
3.1 使用new关键字创建对象
//Student.java
package com.oop.demo01;
//学生类
public class Student {
//属性
String name; //默认值null
int age; //默认值0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//Application.java
package com.oop.demo01;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//类实例化后返回一个对象
//student对象就是Student类的一个具体实例
// Student student = new Student();
// student.study();
Student jack = new Student();
Student rose = new Student();
jack.name = "jack";
jack.age = 11;
System.out.println(jack.name);
System.out.println(jack.age);
System.out.println(rose.name);
System.out.println(rose.age);
}
}
3.2 构造器详解
- 一个类即使什么都不写,也会存在一个方法;
- 构造器:名称必须和类名相同;必须没有返回类型,也不能写void,类似python的__init__方法
this()等同于调用构造器方法
package com.oop.demo01;
public class Person {
//显式定义构造器
String name;
//实例化初始值
//使用new关键字,本质实在调用构造器
//无参定义
public Person(){
this.name = "default";
}
//有参定义;定了有参构造,还想使用无参构造,则需显示定义无参构造
public Person(String name){
this.name = name;
}
}
生成构造器快捷键
3.3 创建对象内存分析
四、封装
将属性私有化,通过get和set方法访问和修改,在set方法中添加安全性校验
private关键字:私有,只能在类内部访问,类外部无法访问
public:类内部和外部都能访问
package com.oop.demo02;
public class Student {
//属性私有
private String name; //名字
private int age; //年龄
private char gender; //名字
//提供一些可以操作属性的方法
//提供一些public的get、set方法
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age) {
if(age>0 && age<100){
this.age = age;
}else{
this.age = 0;
}
}
}
封装的意义:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 提高系统的可维护性
五、继承
子类继承父类,就会拥有父类的全部方法和属性
<私有的可以继承但无法直接访问!!!!>
5.1 object类
快捷键:ctrl+H
在java中,所有的类都默认直接或间接继承Object类
5.2 super详解
super注意点:
super()的作用:初始化当前对象的父类特征,并不是创建父类对象
super.关键字代表当前对象的父类型特征
super不是引用,也不保存内存地址,也不指向任何对象
假设子类和父类中出现同名属性,则super不能省略,否则默认为子类属性
- super仅出现在子类的方法或构造方法中
- 子类在实例化时,子类构造函数中默认先调用父类的无参构造函数
- 子类构造方法中如果显式通过super()调用父类的构造方法,必须在第一行
- super()和this()不能同时出现,因为都必须放在第一行
5.3 方法重写
向上转型
添加链接描述
静态方法方法的调用只和左边定义的数据类型有关
静态方法是类的方法,非静态方法是对象的方法
重写总结
- 需要有继承关系,子类重写父类方法
- 方法名必须相同,参数列表相同,返回类型要兼容
- 修饰符:范围可以扩大,但不能缩小;即访问权限不能更严格:public>protected>default>private
- 抛出的异常:范围可以被缩小,但不能扩大;
- 方法一样,方法体不同
注意:
- 私有方法不能继承,所以不能重写
- 构造方法不能继承,所以不能重写
- 静态方法不存在重写
为什么需要重写
- 父类的功能,子类不一定需要或不一定满足
- Alt+insert ;override
六、多态
Student()实例既可以是Student类型,也可以是Person类型;但声明为Person类型,就只能使用Person类的方法
多态注意事项:
- 多态是方法的多态,属性没有多态
- 父类和子类。有联系
- 存在的条件:有继承关系,方法需要重写,父类引用指向子类
- static方法属于类,不属于实例,无法重写
- final修饰的,无法重写
- private修饰的,无法重写
- 方法中形参声明为父类,实参可以为任意子类对象
七、instanceof和类型转换
7.1 instanceof关键字
含义:判断一个对象是什么类型
- X instanceof Y能否编译通过:看对象X的类型(左边)和Y的类型有无父子关系
- X instanceofY结果为true还是false:看对象X的引用指向对象(右边)是否为Y的类或子类
编译看左,运行看右!!!
package com.oop;
import com.oop.demo04.Person;
import com.oop.demo04.Student;
import com.oop.demo04.Teacher;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//Object>String
//Object>Person>Student
//Object>Person>Teacher
Object o = new Student();
System.out.println(o instanceof Student);//true
System.out.println(o instanceof Person);//true
System.out.println(o instanceof Object);//true
System.out.println(o instanceof Teacher);//false
System.out.println(o instanceof String);//false
System.out.println("===========================");
Person p = new Student();
System.out.println(p instanceof Student);//true
System.out.println(p instanceof Person);//true
System.out.println(p instanceof Object);//true
System.out.println(p instanceof Teacher);//false
// System.out.println(p instanceof String);//编译报错,Person和String同级,没有联系
System.out.println("===========================");
Student s = new Student();
System.out.println(s instanceof Student);//true
System.out.println(s instanceof Person);//true
System.out.println(s instanceof Object);//true
// System.out.println(s instanceof Teacher);//编译报错
// System.out.println(s instanceof String);//编译报错
System.out.println("===========================");
Person per = new Person();
System.out.println(per instanceof Student);//false
System.out.println(per instanceof Person);//true
System.out.println(per instanceof Object);//true
}
}
7.2 类型转换
package com.oop;
import com.oop.demo04.Person;
import com.oop.demo04.Student;
import com.oop.demo04.Teacher;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//类型之间转换:父<====>子
// 高<====>低
Person p = new Student();
//将p这个对象转成Student类型,高转低,需要强转
// Student s = (Student) p;
((Student) p).eat();
Student s2 = new Student();
//将s2这个对象转成Person类型,低转高,自动转换
//子类转成父类,可能丢失自己本来的一些方法
Person p2 = s2;
}
}
总结:
- 父类引用指向子类对象
- 把子类转成父类,向上转型;可能丢失子类中特有方法
- 把父类转成子类,向下转型,需要强制转换,可能丢失父类中私有方法
八、static关键字详解
package com.oop.demo05;
//static
public class Student {
private static int age;//静态变量
private double score;//非静态变量
public void run(){
System.out.println("running");
eat(); //非静态方法中可以调用静态方法;
}
public static void eat(){
System.out.println("eating");
//run();静态方法中不可直接调用非静态方法
}
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.score);
System.out.println(s.age);
System.out.println(Student.age);
Student.eat();
eat();
s.run();
s.eat();
}
}
package com.oop.demo05;
public class Person {
//匿名代码块,第二个执行
{
System.out.println("匿名代码块");
}
//静态代码块,第一个执行,只执行一次
static {
System.out.println("静态代码块");//静态代码块中只能使用static修饰的属性和方法
}
//第三个执行
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person = new Person();
System.out.println("============");
Person person2 = new Person();
}
}
九、抽象类
package com.oop.demo06;
//abstract 抽象类
public abstract class Action {
//abstract 抽象方法:只有方法名字,没有方法实现
public abstract void doSomeThing();
}
======================================
package com.oop.demo06;
//抽象类的子类,需要实现抽象类的抽象方法,除非子类也是抽象类
//extend:单继承,接口可以多继承
public class Test01 extends Action{
@Override
public void doSomeThing() {
}
}
特点:
- 不能new抽象类,只能靠子类实现
- 抽象方法必须在抽象类中
- 抽象类中可以有普通方法
- 抽象的抽象:约束
十、接口的定义和实现
package com.oop.demo07;
//interface关键字,接口都需要有实现类
public interface UserService {
//默认是常量
int AGE = 10;
//接口中的所有定义都是抽象的,默认public abstract
void addName(String name);
void deleteName(String name);
void updateName(String name);
void queryName(String name);
}
========================================
package com.oop.demo07;
//类实现接口,implements 接口
//实现了接口的类,就需要重写接口中的方法
//利用接口实现多实现
public class UserServiceImpl implements UserService,TimeService {
@Override
public void addName(String name) {
}
@Override
public void deleteName(String name) {
}
@Override
public void updateName(String name) {
}
@Override
public void queryName(String name) {
}
@Override
public void timer() {
}
}
作用:
- 约束;
- 定义一些方法,让不同人实现
- 方法修饰符默认都是public abstract
- 属性修饰符默认都是public static final,不需要显示写
- 接口不能直接实例化 ,接口中没有构造方法
- 接口可以继承其他接口
- implements可以实现多个接口
- 实现接口的类必须提供接口中所有方法的具体实现内容(即重写),方可实例化,否则仍为抽象类
- 如果一个类即继承父类,又实现接口;那么先继承,再实现
十一、N种内部类
内部类的主要作用:解决类的多重继承问题
11.1 成员内部类
package com.oop.demo08;
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
======================================
package com.oop;
import com.oop.demo04.Person;
import com.oop.demo04.Student;
import com.oop.demo04.Teacher;
import com.oop.demo08.Outer;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
11.2 静态内部类
package com.oop.demo08;
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
}
}
11.3 局部内部类
package com.oop.demo08;
public class Outer {
private int id=10;
public void method(){
//局部内部类,定义在方法中
class Inner{
}
}
}
11.4 匿名内部类
package com.oop.demo08;
public class Outer {
private int id=10;
public static void main(String[] args) {
//没有名字初始化类,不讲实例保存到变量中
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("eeee");
}
}
一个java文件中最外层可以有多个class,但只能有一个public class