1、面向对象编程:OOP(Object-Oriented Programming,OOP)
2、以类的方式组织代码,以对象的组织(封装)数据
3、抽象
4、三大特性:继承、封装、多态
5、对象是具体的事务;类是抽象的(对对象的抽象);类是对象的模板
6.1类与对象的关系
类(现实对象的模板)是一种抽象的数据类型,对某一类事务整体描述/定义;但是不能代表一个具体的事务
·动物、植物、家电、、、、
·Person类、Pet类、Car类
·在一组相同或者类似的对象中,抽取出共性的特征和行为,保留所关注的部分
对象是抽象概念的具体实例
·张三是一个人的的具体实例
·能够体现出特点,展现出功能的具体实例,而不是抽象概念
·将对象保存在相同类型的实例名(对象名/引用名)变量中
·访问属性:
* 对象名.属性名 = 值; //赋值
* 对象名.属性名 //取值
调用方法:
* 对象名.方法名();
6.2创建于初始化对象
1、使用new关键字创建。分配内存空间+默认初始化+对类中构造器的调用
2、构造器也成为构造方法,创建对象时必须调用;其特点:必须和类名相同;必须没有返回类型,也不能写void
package com.oop.object;
//学生类
public class Student {
//属性:字段
String name;
boolean sex;//1:boy 2:girl
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
/**
* public class Application {
* public static void main(String[] args) {
* //类是抽象的 需要实例化
* Student student = new Student();
* student.name = "Joey";
* student.sex=true;
* student.age=12;
* student.study();
* }
* }
* */
6.3构造器详解
1、即使什么方法都不写,也存在一个默认的无参构造器;
2、无参构造器可以实例化对象(值初始化)
3、使用new关键字,本质实在调用构造器。
package com.oop.object;
public class Person {
String name;
//快捷键:alt+insert ==》生成构造器
//显示定义(无参)构造器
public Person(){
// this.name = "Joey";
}
//有参构造器 : 一旦定义了有参构造,无参构造必须显示定义
public Person(String name){
this.name = name;
}
}
6.4小结
1、类与对象;类是一个模板:抽象,对象是一个具体的实例
2、方法:定义&调用(避免方法死循环)
3、对象的引用:
引用类型: 基本类型(8种)
对象是通过引用来操作的:栈 ---》 堆
4、属性 :字段Field成员变量
默认初始化:
数字:0 0.0
char
:u0000
boolean
:false
引用:null
修饰符 属性类型 属性名 = 属性值
5、对象的创建和使用
-必须使用new关键字来创建(默认的无参构造器,自定义有参构造器(必须显示定义无参构造器))
Person p = new Person();
-对象的属性 : p.name
-对象的方法: p.hello
()
6、类
静态的属性 属性
动态的行为 方法
7、局部变量(要求先赋值再使用,否则报未初始化错误)与实例变量区别
变量的属性 | 局部变量 | 成员变量(实例) |
---|---|---|
定义位置 | 方法或者方法内部结构当中 | 类的内部,方法的外部 |
默认值 | 无 | 字面值(与数组相同) |
使用范围 | 从定义行、列到包含其结构结束 | 本类有效 |
命名冲突 | 不允许重名 | 可与局部变量重名(局部变量优先) |
7.面向对象-三大特性
7.1封装
封装:数据的隐藏
程序设计追求“高内聚,低耦合”
私有属性:get/set
封装的意义:
1、提高了程序的安全性
2、隐藏代码的实现细节
3、统一接口
4、系统可维护性增强
package com.oop.encapsulation;
public class Student {
//姓名
private String name;
//学号
private int ID;
//年龄
private int age;
//性别 1:boy 2:girl
private boolean sex;
//专业
private String major;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = ID;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
}
7.2继承
Java中所有的类都默认直接或者间接继承Object类
继承的本质是对某一批类的抽象
extends是“扩展”;即子类是父类的扩展(子类会拥有父类的全部公共(public)方法)
Java中只有单继承没有多继承(一个儿子可以有一个爸爸,一个爸爸可以有多个儿子)
继承是类与类之间的关系,除了继承以外还有依赖、组合、聚合
继承关系的两个类,一个为子类(派生类),一个为父类(基类)
Object类、super、方法重写
7.2.1 super详解
super注意点:
1、super调用父类的构造方法,必须处于代码(构造方法)中的第一行
2、super必须只能出现在子类的方法或者构造方法中
3、super和this不能同时调用构造方法
VS this:
代表的对象不同:
this:本身调用本类的对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承条件下才能使用
构造方法:
this():本类的构造
super():父类的构造
Person(父类)
package com.oop.inherit;
public class Person {
//父类无参构造
public Person(){
System.out.println("父类无参构造");
}
//父类有参构造
public Person(String name){
System.out.println("父类有参构造");
}
//人的特性
public void say(){
System.out.println("Say Hello!!!");
}
protected String name = "Joey";
public void print(){
System.out.println("Person");
}
}
Student(子类)
package com.oop.inherit;
public class Student extends Person{
public Student(){
super();
System.out.println("子类无参构造");
}
public Student(String name){
System.out.println("子类有参构造");
}
private String name = "Rose";
public void test(String name){
System.out.println(name);//main中的参数名
System.out.println(this.name);//Student类本类中的名字
System.out.println(super.name);//父类中的名字
}
public void print(){
System.out.println("Student");
}
public void test1(){
print(); //当前类对象
this.print(); //当前类对象
super.print(); //父类对象
}
}
/*
* public class Application {
public static void main(String[] args) {
Student s = new Student();
s.test("乔伊");
s.test1();
}
}
* */
7.2.2方法重写
重写是方法的重写;与属性无关
重写注意点:
1、需要有继承关系;子类重写父类的方法
2、方法名必须相同
3、参数列表也必须相同
4、修饰符:范围可以扩大,但是不能缩小 public>protected>Default>private
5、抛出的异常:范围可以被缩小,但是不能扩大:ClassNotFoundException
--->Exception(大)
6、子类和父类方法必须一致;方法体不同
为什么需要重写?
1、父类的功能子类不一定需要
2、Alt+Insert 选中Override(重写)
不能被重写的情况:
1、static 方法属于类,不属于实例
2、final 常量 不能被重写
3、private 方法不能被重写
B类(父类)
package com.oop.inherit;
public class B {
public static void test(){
System.out.println("B=>test()");
}
public void test1(){
System.out.println("B=>test1()");
}
}
A类(子类)
package com.oop.inherit;
public class A extends B{
public static void test(){
System.out.println("A=>test()");
}
7.3多态
同一方法根据发送对象的不同而采用不同的行为方式
动态编译:类型;可扩展性变强;屏蔽子类间的差异;灵活,耦合度低
多态存在的条件:
有继承关系
子类重写父类的方法
父类引用指向子类对象
多态是方法的多态,属性没有多态性
多态的注意点:
1、多态是方法的多态,属性没有多态
2、父类和子类有联系,否则会有类型转换异常:ClassCastException
3、存在的条件: 继承关系;方法需要重写;父类引用指向子类对象
4、子类转为父类:向上转型
5、父类转为子类:向下转型(需要强制转换)
6、方便方法的调用,减少重复的代码!简介
package com.oop.polymorphic;
//父类
public class Father {
public void run(){
System.out.println("Dad running!");
}
}
package com.oop.polymorphic;
public class Son extends Father{
7.3.1 instanceOf
类型(引用)转换
public class Application {
//instanceof 判断是否存在父子关系 是返回true 否则false
public static void main(String[] args) {
//Object > Father > Son
//Object > String
Object o = new Son();
System.out.println(o instanceof Son);
System.out.println(o instanceof Father);
System.out.println(o instanceof Object);
System.out.println(o instanceof String);
}
}
/*
* public static void main(String[] args) {
Son s = new Son();
Father f = new Son(); //父类的引用指向子类的类型
Object o = new Son();
s.run();
f.run(); //子类重写父类方法,执行子类的方法
//对象能够执行哪些方法,主要看对象左边的类型
s.eat();
((Son) f).eat(); //强制转换f为Son类型
}*/
7.3.2多态的应用
场景一:使用父类作为方法形参实现多态,使方法的参数类型更为宽泛
场景二:使用父类作为方法返回值实现多态,使方法可以返回不同的子类对象
7.3.3装箱
向上转换:父类引用中保存真实的子类对象,称为向上转型(多态核心)
Animal a = new Dog();
7.3.4插箱
向下转型(拆箱):将父类引用中的真实子类对象,强行转换为子类本身类型,向下转型。
Dog dog = (Dog)a;
向下转型之前,应该判断引用中的真实子类对象类型,保证类型转换的正确性
8.面向对象-补充
8.1抽象类(abstract)
可以修饰方法(抽象方法)也可以修饰类(抽象类)
抽象类中可以没有抽象方法;但是有抽象方法的类一定要声明为抽象类
抽象类,不能使用new关键字来创建对象,用来让子类继承
抽象方法:只有方法的声明,没有方法的实现,用来让子类实现的
子类继承抽象类,必须实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
package com.oop.others;
//该类为抽象类
public abstract class Action {
//抽象方法 只有方法的约束 没有方法体
public abstract void doSomething();
/*
* 1、不能new抽象类,只能靠子类取实现它:约束
* 2、抽象类中可以写普通的方法
* 3、抽象方法必须在抽象类中
* */
}
package com.oop.others;
//abstract 抽象类; 类 extends:单继承(接口可以实现多继承)
//子类继承抽象类,必须实现抽象类中所有的方法;除非子类也是一个抽象类
public class A extends Action{
public void doSomething() {
System.out.println("继承抽象类A ");
}
}
8.2接口
interface
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范!自己无法写方法;约束和实现分离
接口就是规范(定义的一组规则;本质==契约;面向对象(OO
)的精髓)
作用:
1、约束(定义一些规则)
2、定义一些方法,让不同的人实现
3、默认方法:public abstract
4、默认常量:public static final
5、接口不能被实例化;接口中没有构造方法
6、implements可以实现多个接口
7、必须要重写接口中的所有的方法
与抽象类的异同:
相同点 | 不同点 |
---|---|
可编译字节码文件 | 所有属性都是公开静态常量,隐式使用public static final 修饰 |
不能创建对象 | 所有方法都是公开抽象方法,隐式使用public abstract 修饰 |
可以作为引用对象 | 没有构造方法和静态代码块 |
具备Object类中的所有定义的方法 |
接口引用:
类与类:单继承;extends 父类名称
类与接口:多实现;implements 接口名称1,接口名称2,,,接口名称n
接口与接口:多继承;extends 父接口1,2,3,,,,n
package com.oop.others;
//interface 接口的关键字
//接口都需要实现类
public interface UserService {
//常量 默认:public static final
public static final boolean sex = true;
int age = 21;
/*方法默认为 public abstract ;接口中所有的定义都是抽象的*/
void run();
void eat(String name);
}
package com.oop.others;
public interface TimeService {
void checkTime();
}
package com.oop.others;
//抽象类:extends~
//类 可以实现接口 implements 接口
//重写接口里面的所有方法
public class UserServiceImpl implements UserService,TimeService{ //多继承(利用接口)
public void run() {
System.out.println("running");
}
public void eat(String name) {
System.out.println(name+"eating");
}
public void checkTime() {
System.out.println("现在是北京时间:");
}
}
8.3内部类
特点:
-编译后可以独立的生成字节码文件
-内部类可以直接访问外部类的私有成员,而不破坏封装
-可以为外部类定义必要的组件
一个类的内部在定义一个类
1、成员内部类
-类的内部定义,与实例变量和实例方法同级别的类
-外部类的一个实例部分,创建对象时,必须依赖外部类对象
-当外部类和内部类存在重名属性,优先访问内部类属性
-成员内部类不能定义静态成员
2、静态内部类
-不依赖外部类对象,可直接创建或者通过类名访问,可声明静态成员
-只能访问外部类的静态成员(实例成员需要实例化外部类对象)
3、局部内部类
-定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
-局部内部类访问当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final
-限制类的使用范围
4、匿名内部类
-没有类名的局部内部类(其余特征与局部内部类相同)
-必须继承一个父类或者实现一个接口
package com.oop.inner;
public class Outer {
protected String sex;
private int id = 10;
public String name;
public void out(){
System.out.println("外部类方法输出");
}
public class Inner{
public void in(){
System.out.println("这是内部类的输出");
}
//获得私有属性
public void getId(){
System.out.println(id);
}
}
}
/*
* public static void main(String[] args) {
Outer outer = new Outer();
//通过外部类实例化内部类
Outer.Inner inner = outer.new Inner();
inner.getId();
}
* */