面向对象编程 OOP

面向对象&面向过程

面向对象编程的本质:以类的方式组织代码,以对象的方法组织数据

面向对象编程的三大特征:

  • 封装

  • 继承

  • 多态

方法

  • 静态方法

    通过 static 关键词说明

    调用方法:通过方法名直接调用

  • 动态方法

    无static关键词

    调用方法:实例化后通过实例直接调用

    Student student = new Student();
    student.say();

值传递和引用传递

值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

public class OopDemo04 {
public static void main(String[] args) {
int a=1;
System.out.println(a);
change(a); // 值传递
System.out.println(a);
System.out.println("============");
Students students =new Students();
System.out.println(students.num);
add(students); // 引用传递
System.out.println(students.num);
}
public static void change(int a){
a = 10;
return ;
}
public static void add(Students students){
students.num++;
}
}
class Students { // 一个java文件里面只有一个 public class
int num = 10;
}

类和对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物的整体描述,但并不代表某个具体事物

  • 对象是抽象概念的具体实例

创建对象

使用new关键字创建对象

创建时除了分配内存空间外,还会给创建好的对象进行默认初始化以及对类中的构造器进行调用

类中构造器也称构造方法,在创建对象时必须进行调用,并且构造器有以下连个特点:

  • 必须和类的名字相同

  • 必须没有返回类型,也无void

    public class Person {
    public Person() {
    }
    }

创建实例

public class Application {
public static void main(String[] args) {
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "xiaoming";
xiaohong.name = "xiaohong";
xiaohong.age = 10;
xiaoming.age = 11;
System.out.println(xiaohong.name);
System.out.println(xiaoming.age);
xiaohong.study();
}
}

定义一个显示构造器

  • 无参构造

    public class Person {
    String name;
    // 一个类必须有构造器 // 显示构造
    // 无参构造
    public Person(){
    this.name = "NiDie";
    }
    }
  • 有参构造

    public class Person {
    String name;
    // 一个类必须有构造器 // 显示构造
    // 有参构造,必须显示定义
    public Person(String name){
    this.name = name;
    } // 定义了一个有参构造后,要调用无参构造,必须显示定义一个无参构造
    public Person() {
    }
    // Alt + insert <Conductor> 生成构造器
    }

    内存分析

    public class Application {
    public static void main(String[] args) {
    Pet dog = new Pet();
    dog.name = "WangCai";
    dog.age = 3;
    Pet cat = new Pet();
    }
    }
    public class Pet {
    String name;
    int age;
    }

    内存状况

封装

封装的好处

  • 提高系统的安全性

  • 隐藏代码的实现细节

  • 统一接口

  • 增加系统的可维护性

    public class Student {
    private String name;
    private String id;
    private char sex;
    // 私有属性可以通过一些public的方法进行操作--get/set
    public String getName(){
    return this.name;
    }
    public void setName(String name){
    this.name = name;
    }
    // Alt + Insert +<Sitter and Getter>生成get和set方法 public String getId() {
    return id;
    } public void setId(String id) {
    if(id.length()==10)
    this.id = id; // 合法性检验
    else
    System.out.println("Wrong input");
    }
    }

继承

在Java中所有类直接或间接的继承Object类

一个类只有一个父类,可以有多个子类

public class Person {
int age;
String name;
char sex;
// public
// protected
// default
// private
private double money; public void say(){
System.out.println("Fuck!");
} public double getMoney() {
return money;
} public void setMoney(double money) {
this.money = money;
}
// Ctrl + H 打开类的层次结构
}
// Student子类
// 子类继承了父类就会有父类的部分方法和属性
// 私有属性无法被继承
public class Student extends Person{
}

super注意点

  • super调用父类的构造方法,必须在构造方法的第一个
  • super必须只能出现在子类的方法或构造方法中
  • super和this不能同时调用构造方法
  • this和super代表的对象不同,this时本身调用者这个对象,super代表父类的应用
  • this没有继承也可以使用,super必须在继承时才能使用
  • this(); --本类的构造,super(); --父类的构造
// Student子类
// 子类继承了父类就会有父类的全部方法和部分属性
// 私有属性无法被继承
public class Student extends Person{ public Student() {
// 隐藏代码:调用父类构造器super();
super();//调用父类或自己的构造器,必须在子类或自己构造器的第一行
} String name = "WhiteDog";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public void say(){
System.out.println("You!");
}
public void say1(){
say();
this.say();
super.say();
}
}

重写注意

  • 需要有继承关系,子类重写父类的方法

    1. 方法名必须相同
    2. 参数列表必须相同
    3. 修饰符:范围可以扩大但不能缩小: public > protected > default>private
    4. 抛出异常:范围,可以被缩小,但不能扩大:
  • 子类和父类的方法必须一致:方法体不同

  • 为什么要重写

    1. 父类的功能不一定需要,或不满足
    public class A {
    public void test(){
    System.out.println("A->test");
    }
    }
    //重写都是方法的重写,和属性无关
    public class B extends A{
    //override 重写
    // Alt + Insert +<override> 实现重写
    @Override//注解:有功能的注释
    public void test() {
    System.out.println("B->test");
    }
    }
    public class Application {
    public static void main(String[] args) {
    // 静态方法的调用只和左边定义的数据类型有关
    // 非静态方法才能实现方法重写
    // B b = new B();
    // b.test();
    // //父类的引用可以指向指向子类
    // A a = new A();
    // a.test();
    B b = new B();
    b.test();
    //父类的引用可以指向指向子类
    A a = new A();
    a.test();
    }
    }

多态

Java的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。

多态存在允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码。

public class Person {
public void fuck(){
System.out.println("Fuck");
}
} public class Student extends Person{
@Override
public void fuck() {
System.out.println("Fuck You");
}
public void eat(){
System.out.println("Shit!");
}
}
public class Application {
public static void main(String[] args) {
// 一个类型的实际类型时确定的
//new Person();
// new Student();
// 指向的引用类不确定:父类的引用指向子类 // Student 能调用的方法都是自己的或者继承的父类
Student s1 = new Student();
// Person 父类型 可以指向子类,但不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student(); //对象能执行哪些方法,主要看左边的类型
s1.fuck(); s2.fuck(); // 子类重写了父类的方法,执行子类的方法
((Student) s2).eat(); // 类型强制转换
}
}

多态注意事项

  1. 多态的方法是多态的

  2. 父类不能执行子类的方法,会出啊先类型转换异常

  3. 多态存在条件:继承关系;方法重写;父类引用指向子类对象

  4. 以下方法不能重写

    • static方法,属于类但不属于实例
    • final常量
    • private方法
  5. 继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final。用final修饰的方法不能被Override

  6. 如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final。用final修饰的类不能被继承

  7. 对于一个类的实例字段,同样可以用final修饰。用final修饰的字段在初始化后不能被修改

instanceof关键字

instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例

boolean result = obj instanceof Class

其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。

注意:编译器会检查 obj 是否能转换成右边的class类型,如果不能转换则直接报错,如果不能确定类型,则通过编译,具体看运行时定。

类型转换

public class Application {
public static void main(String[] args) {
// 子类转换为父类,可能会丢失部分方法
Student student = new Student();
student.eat();
Person person = student;
// person.eat();报错,丢失方法
((Student) person).eat();//再向子类强制转换
}
}

父类向子类转型需要强制转换

类型转换方便方法的调用,减少重复代码

static关键字

静态变量

public class Student {
static int age; //静态变量
private double score; //非静态变量 public static void main(String[] args) {
Student s1 = new Student();
System.out.println(s1.score);//非静态变量只能实例化后引用,对于方法也一样
System.out.println(s1.age); //静态变量可直接在类中直接引用,也可实例化后应用
System.out.println(age);
say();
s1.piss();
}
public static void say(){
System.out.println("Hi");
}
public void piss(){
System.out.println("Pee");
}
}

Java代码块

public class Person {
//2:每次都执行,可用于赋初值
{
System.out.println("匿名代码");
}
//1:只执行一次
static {
System.out.println("静态代码");
}
//3
public Person(){
System.out.println("构造方法");
} public static void main(String[] args) {
Person person = new Person();
System.out.println("======");
Person person1 = new Person(); }
}

导入常量和方法

//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Application {
public static void main(String[] args) {
System.out.println(Math.random());
System.out.println(random());
System.out.println(PI);
}
}

抽象类

// abstract 抽象类
public abstract class Action {
//abstract 抽象类只有方法没有实现
public abstract void doIt();
}
//抽象类的所有方法,继承了它的子类,都必须实现它的方法
public class A extends Action{
@Override
public void doIt() { }
}

抽象类的特点

  1. 不能被实例化new,只能靠子类去实现,相当于约束
  2. 抽象类可以写普通方法
  3. 抽象方法必须定义在抽象类中
  4. 抽象的抽象:约束

接口

接口:只有规范,定义了一组规则

关键字:interface

接口没有构造方法,不能被实例化

public interface UserService {
int AGE = 1;// 接口可以定义静态常量 // 抽象类中定义都是抽象的 public abstract
public abstract void run();
void add(String name);
void delete(String name);
void update(String name);
void query(String name); }
public interface TimeService {
void timer();
}
// 类 可以继承接口,关键子implement
// Class implement Interface
// 继承接口后,需要重写接口的所有方法
// 多继承,一个类可以继承多个接口
public class UserServiceImp implements UserService,TimeService{
@Override
public void run() { } @Override
public void add(String name) { } @Override
public void delete(String name) { } @Override
public void update(String name) { } @Override
public void timer() { } @Override
public void query(String name) { }
}

内部类

在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。

成员内部类

定义

class C{
class D{ }
}

成员内部类可以无条件访问外部类的属性和方法,但是外部类想要访问内部类属性或方法时,必须要创建一个内部类对象,然后通过该对象访问内部类的属性或方法

class C{
private String name = "外部类";
public void run(){
System.out.println("外部类奔跑");
}
class D{
public void say(){
System.out.println(name);
run();
}
}
}
class C{
private String name = "外部类";
public void run(){
System.out.println("外部类奔跑");
}
/*使用内部类的属性和方法*/
public void eat(){
D d = new D();
System.out.println(d.value);
d.say();
}
class D{
private String value = "DDD";
public void say(){
System.out.println(name);
run();
}
}
}

外部类属性或方法隐藏

如果成员内部类的属性或者方法与外部类的同名,将导致外部类的这些属性与方法在内部类被隐藏,也可按照该格式调用,外部类.this.属性/方法。

class C{
private String name = "外部类";
public void run(){
System.out.println("外部类奔跑");
}
/*使用内部类的属性和方法*/
public void eat(){
D d = new D();
System.out.println(d.value);
d.say();
}
class D{
private String value = "DDD";
private String name = "内部类";
public void say(){
System.out.println(C.this.name);
System.out.println(name);
run();
}
}
}

创建内部类对象

public class Test10 {
public static void main(String[] args) {
/*方式1创建成员内部类对象*/
C c = new C();
C.D d = c.new D();
/*方式2创建成员内部类对象*/
C.D d1 = c.getClass();
}
}

成员内部类的访问权限

成员内部类前可加上四种访问修饰符。

  • private:仅外部类可访问。
  • protected:同包下或继承类可访问。
  • default:同包下可访问。
  • public:所有类可访问。

局部内部类

局部内部类存在于方法中。

他和成员内部类的区别在于局部内部类的访问权限仅限于方法或作用域内

class K{
public void say(){
class J{ }
}
}

匿名内部类

public class Test13 {
public static void main(String[] args) {
driveCar(new Car(){
@Override
public void drive() {
System.out.println("驾驶着BMW汽车");
}
});
}
public static void driveCar(Car car){
car.drive();
}
} interface Car {
void drive();
}

分析以上代码知道静态方法driveCar需要一个Car对象,我们通过实现接口创建一个匿名类对象传递过去。事实上还可以通过继承类来创建一个匿名内部类对象。

注意事项

  • 匿名内部类没有构造方法。也是唯一没有构造方法的内部类。

  • 匿名内部类和局部内部类只能访问外部类的final变量。

静态内部类

静态内部类和成员内部类相比多了一个static修饰符。它与类的静态成员变量一般,是不依赖于外部类的。同时静态内部类也有它的特殊性。因为外部类加载时只会加载静态域,所以静态内部类不能使用外部类的非静态变量与方法。

同时可以知道成员内部类里面是不能含静态属性或方法的。

class U {
static class I { }
}

内部类好处

  1. 完善了Java多继承机制,由于每一个内部类都可以独立的继承接口或类,所以无论外部类是否继承或实现了某个类或接口,对于内部类没有影响。
  2. 方便写事件驱动程序。

Java学习笔记--面对对象OOP的更多相关文章

  1. Java学习笔记之对象的复制和克隆

    假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(boolean,char,byte,short, ...

  2. java学习笔记之对象序列化

    1.简述 java对象序列化就是将对象编程二进制数据流的一种方法,从而实现对对象的传输和存储 2.作用 java是门面向对象编程语言,即一切皆对象,但是java对象只能存在于jvm中,一旦jvm停掉那 ...

  3. java学习笔记-01.对象入门

    1.面向对象编程简称是OOP. 2.继承是通过 extends关键字实现的,接口是通过implements关键字实现的. 3.public:意味着后续的定义任何人均可使用. private:意味着除了 ...

  4. java学习笔记-8.对象的容纳

    1.Iterator(迭代器)和Enumeration(枚举类),都是用来遍历集合的,他们都是接口.区别是Enumeration只能读取集合的数据,而Iterator可以对数据进行删除,Iterato ...

  5. Java学习笔记day08_day09_对象实例化_private_this

    1.类与对象 类就是一个模版. 对象的实例化就是根据模版类, 使用new关键字创建实际的对象. 2.类的定义及创建对象 类的定义格式: public class 类名{ //属性(变量) 数据类型 变 ...

  6. java学习笔记之OOP(二)

    java学习笔记二.面向对象[OOP]Object Oriented Programming 一.三大特性: 1.封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用 ...

  7. Java学习笔记之---类和对象

    Java学习笔记之---类和对象 (一)类 类是一个模板,它描述一类对象的行为和状态  例如:动物类是一个类,动物们都有属性:颜色,动物们都有行为:吃饭 public class Dog { Stri ...

  8. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

  9. 20145230《java学习笔记》第七周学习总结

    20145230 <Java程序设计>第7周学习总结 教材学习内容 Lambda语法概览 我们在许多地方都会有按字符串长度排序的需求,如果在同一个方法内,我们可以使用一个byName局部变 ...

随机推荐

  1. 【LeetCode】796. 旋转字符串

    796. 旋转字符串 知识点:字符串:KMP算法: 题目描述 给定两个字符串, A 和 B. A 的旋转操作就是将 A 最左边的字符移动到最右边. 例如, 若 A = 'abcde',在移动一次之后结 ...

  2. Shell-15-脚本练习

    批量生成随机字符串文件名 # 用for循环在 /test 目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字符加固定字符串 alnk #!/bin/bash ########### ...

  3. Redis-03-集群

    集群介绍 Redis Cluster 是 redis 的分布式解决方案, 在3.0版本正式推出,当遇到单机.内存.并发.流量等瓶颈时,可以采用Cluster架构方案达到负载均衡目的 Redis Clu ...

  4. 深入理解-dl_runtime_resolve

    深入理解-dl_runtime_resolve 概要 目前大部分漏洞利用常包含两个阶段: 首先通过信息泄露获取程序内存布局 第二步才进行实际的漏洞利用 然而信息泄露的方法并不总是可行的,且获取的内存信 ...

  5. Python - typing 模块 —— Callable

    前言 typing 是在 python 3.5 才有的模块 前置学习 Python 类型提示:https://www.cnblogs.com/poloyy/p/15145380.html 常用类型提示 ...

  6. VRRP的基本配置

    一.实验拓扑 二.实验编址 三.实验步骤: 1.设置PC的IP等信息 2.启动设备(全选) 3.设置路由器端口ip 4. 配置ospf网络 查看: 5.配置VRRP协议 配置完成后查看: 6.验证主备 ...

  7. 如何快速方便的生成好看的接口文档(apipost生成文档)

    一键生成文档 我们在"2分钟玩转APIPOST"一讲中,简单介绍了如何生成并分享接口文档: 点击分享文档 复制并打开文档地址就可以看到了完整的接口文档. 本节课主要是讲解一些需要注 ...

  8. deepin设置jdk全局变量

    sudo vim /etc/bash.bashrc 在文件最后边添加 JAVA_HOME=jdk地址CLASSPATH=.:$JAVA_HOME/bin.tools.jarPATH=$JAVA_HOM ...

  9. Windows下安装RocketMQ

    目录 前言 环境 具体操作 下载 环境变量配置 启动 关闭 生产.消费实例 RocketMQ Console 前言 项目中用到了延迟消息队列,记录下一win10下rocketmq的安装 环境 win1 ...

  10. Specification使用notin

    废话不多说直接贴代码 Specification<Employee> employeeSpecification = new Specification<Employee>() ...