Java面向对象

面向过程&面向对象

  1. 面向过程:
  • 步骤简单清晰,第一步->第二步->....
  • 面向过程适合处理一些较为简单的问题
  1. 面向对象:
  • 分类的思维模式
  • 面向对象适合处理复杂的问题
  1. 对于描述复杂的事物,使用面向对象的思维去宏观上把握、整体上分析,使用面向过程的思维去处理围观操作

什么是面向对象

  1. 面向对象编程:(Object-Oriented Programming,OOP)
  2. 面向对象编程的本质就是:以类的方式组织代码,以对象的方式组织数据
  3. 3大特性:封装,继承和多态
  4. 从代码运行的角度考虑是先有类后有对象,类是对象的模板

回顾方法的定义

  • 修饰符
  • 返回类型
  • break和return的区别:break 跳出switch选择或者跳出当前循环;return结束方法和返回返回值
  • 方法名:注意驼峰命名原则,见名知意
  • 参数列表:参数类型、参数名;...可变参数->类似于可变数组
  • 异常抛出:常见的有数组下标越界 ArrayIndexOutOfBounds
package com.oop.demo01;
//Demo01类
public class Demo01 {
    //main方法
    public static void main(String[] args) {
        Demo01 demo01 = new Demo01();
        String str = demo01.sayHello();
        System.out.println(str);
        int max = demo01.max(2,1);
        System.out.println(max);
    }
    /*
    修饰符 返回值类型 方法名(参数列表){
        //方法体
        return 返回值;
    }
     */
    public String sayHello(){
        return "hello!";
    }
    public int max(int a,int b){
        return a>b ? a : b;         //三元运算符
    }

}

回顾方法的调用:递归

  • 静态方法、非静态方法
package com.oop.demo01;
//情况1
public class Student {
    //非静态方法
    public void say(){
        System.out.println("学生说话了");
    }
}
public class Demo02 {
    public static void main(String[] args) {
        //实例化这个类 new
        //对象类型 对象名 = 对象值
        Student student = new Student();
        student.say();
        Demo02.a();
    }
    //静态方法和类一起加载
    public static void a(){
        Demo02.b();
    }
	//静态方法和类一起加载
    public static void b(){
        System.out.println("b");
    }

}
package com.oop.demo01;
//情况2
public class Student {
    //非静态方法
    public void say(){
        System.out.println("学生说话了");
    }
}
public class Demo02 {
    public static void main(String[] args) {
        //实例化这个类 new
        //对象类型 对象名 = 对象值
        Student student = new Student();
        student.say();
        Demo02.a();


    }
    //静态方法和类一起加载
    public static void a(){
        Demo02 demo02 = new Demo02();
        demo02.b();
    }
    //类实例化后才存在
    public void b(){
        System.out.println("b");
    }

}
  • 形参和实参
package com.oop.demo01;
public class Demo03 {
    //实际参数与形式参数要对应
    public static void main(String[] args) {
        int add = Demo03.add(1,2);					//1,2是实际参数
        System.out.println(add);
    }
    public static int add(int a, int b){   			//a,b是形式参数
        return a+b;
    }
}
  • 值传递和引用传递
package com.oop.demo01;
public class Demo04 {
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a);              //1
        Demo04.change(a);                   //值传递
        System.out.println(a);              //1
    }
    //返回值为空
    public static void change(int a){       //a是局部变量,只能在方法里生存
        a = 10;
    }
}
package com.oop.demo01;
//引用传递:对象,本质还是值传递
public class Demo05 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);
        System.out.println(person.age);
        Demo05.change(person);
        System.out.println(person.name);
        System.out.println(person.age);
    }
    public static void change(Person person){   //person是实例变量,从属于对象Demo05
        person.name = "huangshen";
        person.age = 20;
    }
}

//定义了一个Person类,有一个属性:name
class Person{
    String name;                                //null
    int age;                                    //0
}

类与对象的创建

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物
  • 对象是抽象概念的具体实例
package com.oop.demo02;
public class Student {
    //属性
    String name;        //null
    int age;            //0

    //方法
    public void study(String name){
        System.out.println(this.name+"在学习");
    }
}
public class Aplication {
    public static void main(String[] args) {
        //类:抽象的,需要实例化
        //类实例化后会返回一个自己的对象
        //student对象就是一个Student类的具体实例
        Student xm = new Student();     //创建小明
        xm.name = "小明";
        xm.age = 3;
        System.out.println(xm.name);
        System.out.println(xm.age);
        xm.study(xm.name);

        Student xh = new Student();     //创建小红
        xh.name = "小红";
        xh.age = 3;
        System.out.println(xh.name);
        System.out.println(xh.age);
        xh.study(xh.name);
    }
}

构造器详解

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象,进行默认的初始化以及对类中构造器的调用
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。
  • 并且构造器有以下两个特点:
  1. 必须和类的名字相同
  2. 必须没有返回类型,也不能写void
  • 构造器的作用:
  1. new本质在调用构造方法
  2. 初始化对象的值
  • 注意点:
  1. 定义有参构造后如果想使用无参构造,必须显示的定义一个无参构造
  • Alt + Insert:可以快速定义构造器

  • this. = 可以快速初始化对象的值

package com.oop.demo02;
//java->class
public class Person {
    //一个类即使什么都不写,它也会存在一个方法
    //显示的定义构造器
    String name;
    int age;

    //无参构造
    public Person() {
    }

    //含有一个参数的有参构造
    public Person(String name) {
        this.name = name;
    }

    //含有两个参数的有参构造
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
//一个项目只存一个main方法
public class Aplication {
    public static void main(String[] args) {
        //new实例化一个对象
        Person person = new Person("huangshen",20);
        System.out.println(person.name);
        System.out.println(person.age);
    }
}

创建对象内存分析

package com.oop.demo03;

public class Pet {
    String name;
    int age;
    //无参构造
    public void shout(){
        System.out.println("叫了一声");
    }
}
package com.oop.demo03;

public class Aplication {
    public static void main(String[] args) {
        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 3;
        System.out.println(dog.name);
        System.out.println(dog.age);
        dog.shout();
        Pet cat = new Pet();
        System.out.println(cat.name);
        System.out.println(cat.age);
        cat.shout();
    }
}

封装

  • 属性私有,get/set
  • 封装作用:
  1. 提高程序的安全性,保护数据
  2. 隐藏代码的实现细节
  3. 统一接口
  4. 系统可维护性增强
package com.oop.demo04;

public class Pet {
    private String name;
    private int age;
    //无参构造
    public void shout(){
        System.out.println("叫了一声");
    }
    //getName
    public String getName() {
        return name;
    }
    //setName
    public void setName(String name) {
        this.name = name;
    }
    //getAge
    public int getAge() {
        return age;
    }
    //setAge
    public void setAge(int age) {
        this.age = age;
    }
}
package com.oop.demo04;

public class Aplication {
    public static void main(String[] args) {
        Pet dog = new Pet();
        dog.setName("旺财");
        System.out.println(dog.getName());
        dog.setAge(3);
        System.out.println(dog.getName()+dog.getAge()+"岁了");
        dog.shout();

        Pet cat = new Pet();
        cat.setName("嘟嘟");
        System.out.println(cat.getName());
        cat.setAge(3);
        System.out.println(cat.getName()+cat.getAge()+"岁了");
        cat.shout();
    }

继承

  1. 继承的特点:
  • 继承的本质是对某一批类的抽象
  • extends的意思是"拓展"。子类是父类的拓展
  • JAVA中只有单继承,没有多继承
  • 继承是类和类的一种关系。除此以外,类和类之间的关系还有依赖、组合、聚合等
  • 继承关系的两个类,一个为子类,一个为父类。子类继承父类,使用关键字extends来表示
  • 子类和父类之间,从意义上应该具有"is a"的关系

object类

package com.oop.demo05;
//在JAVA中,所有的类都默认直接或者间接继承Object类
//Person是父类
//Ctrl + H 可以查看继承树
public class Person {
    //属性一般是私有的
    //要想使用属性则需要使用封装时留下的方法get/set
    private int money = 10_0000_0000;
    public void say(){
        System.out.println("我喜欢钱!");
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}
package com.oop.demo05;

public class Student extends Person{
}
package com.oop.demo05;

public class Aplication {
    public static void main(String[] args) {
        Student student = new Student();
        student.say();
        student.setMoney(10_0000);
        System.out.println("student有"+student.getMoney()+"元");
    }
}

super

super注意点:
    1.super调用父类的构造方法,必须在构造方法的第一个
    2.super 必须只能出现在子类的方法和或者构造方法中!
    3.super和this 不能同时调用构造方法

VS this:
    1.代表的对象不同:
        this:本身调用者这个对象
        super: 代表父类对象的引用
    2.前提:
        this: 没有继承也可以使用
        super: 只能在继承条件才可以使用
    3.构造方法:
        this();本类的构造
        super();父类的构造
package com.oop.demo06;

public class Person {

    public Person(){        //Person的无参构造
        System.out.println("Person的无参构造");
    }
    /*Person的有参构造,如果在子类Student默认调用,则无法调用,除非调用Person的无参构造
    public Person(String name){
        System.out.println("Person的无参构造");
    }*/
    //如果name是私有的则子类无法继承
    protected String name = "huangshen";
    public void print(){
        System.out.println("Person");
    }
}
package com.oop.demo06;

public class Student extends Person {
    public Student(){              //Student的无参构造
        //隐藏代码:调用了父类的无参构造
        //super("Student");        //调用父类的构造器,必须在子类构造器的第一行
        //this();                  //调用自己的构造器也必须放在第一行但是必须先调用父类的构造器
        System.out.println("Student的无参构造");
    }
    private String name = "huangyilin";
    public void print(){
        System.out.println("Student");
    }
    //this表示当前类,super表示父类
    public void test1(){
        print();            //Student
        this.print();       //Student
        super.print();      //Person
    }
    public void test(String name){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);

    }
}
package com.oop.demo06;

public class Aplication {
    public static void main(String[] args) {
        Student student = new Student();
        student.test("hyl");
        student.test1();
    }
}

方法重写

重写:需要有继承关系,子类重写父类的方法
    1.方法名必须相同
    2.参数列表必须相同
    3.修饰符:范围可以扩大但不能缩小:public>protected>default>private
    4.抛出的异常:范围可以缩小但不能扩大:ClassNotFoundException-->Exception大
重写:子类的方法和父类必须一致,方法体不同!

为什么需要重写:
    1.父类的功能,子类不一定需要或者不一定满足
    Alt + Insert : override;
package com.oop.demo07;

//重写都是方法的重写与属性无关!!!
public class B {
    public  void test(){
        System.out.println("B->test");
    }
}
package com.oop.demo07;

//继承
public class A extends B {
    @Override //注解:有功能的注释
    public void test() {
        System.out.println("A->test");
    }
}package com.oop.demo07;


//静态方法:方法的调用只和左边的数据类型有关
//非静态方法: 重写
public class Aplication {
    public static void main(String[] args) {
        A a = new A();
        a.test();   //A
        //父类的引用指向了子类
        B b = new A();      //子类重写了父类的方法
        b.test();   //B
    }
}


多态

  • 多态的注意事项:
  1. 多态是方法的多态,属性没有多态
  2. 父类和子类,有联系 ,类型转化异常!ClassCastException
  3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
  • static 方法,属于类,不属于实例

  • final 常量

  • private方法

  • 类型转换:

  1. 父类引用指向子类的对象

  2. 把子类转换为父类,向上转型;

  3. 把父类转换为子类,向下转型;强制转换

  4. 方便方法的调用,减少重复的代码!

package com.oop.demo08;

public class Person {
    public void run(){
        System.out.println("run");
    }
}
package com.oop.demo08;

public class Student extends Person {
    @Override
    public void run() {
        System.out.println("son");
    }
    public void eat(){

        System.out.println("eat");
    }
}
package com.oop.demo08;

public class Aplication {
    public static void main(String[] args) {
        //一个对象的实际类型是确定的
        //new Student
        //new Person

        //可以指向的引用类型就不确定了:父类的引用指向子类

        //Student 能调用的方法都是自己的或者继承父类的!
        Student s1 = new Student();
        //Person 父类型,可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
        s1.eat();
        s2.run();   //子类会重写父类的方法,执行子类的方法
    }
}

instanceof

  • 判断两个类型之间是否存在父子关系
  • (对象)instanceof(类型)

static关键字详解

package com.oop.demo09;

//public final class Person {},则Person没有子类
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 person1 = new Person();
        Person person2 = new Person();
    }

}
package com.oop.demo09;

public class Student {
    private static int age; //静态的变量,多线程!
    private double score;   //非静态变量

    public void run(){      //非静态方法,从属于对象
        go();
    }
    public static void go(){    //静态方法从属于类,只加载一次
        System.out.println("go!");
    }

    public static void main(String[] args) {
        Student.go();;
    }
}
package com.oop.demo09;

//静态导入包~
import static java.lang.Math.random;
import static java.lang.Math.PI;

public class Test {
    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
    }
}

抽象类

package com.oop.demo10;
//abstract 抽象类:extends: 单继承 (接口可以多继承)
public abstract class Action {
    //约束~有人帮我们实现
    //abstract ,抽象方法,只有方法名字 , 没有方法的实现
    private String name = "Action";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Action(){
        System.out.println("Action 的构造器");
    }

    public abstract void doSomething();
    public void print(){
        System.out.println("print");
    }
    public void run(){
        System.out.println("run");
    }
    /* 抽象类的特点:
     * 1.不能new这个抽象类,只能靠子类去实现!
     * 2.抽象类中可以写普通的方法!
     * 3.抽象方法必须在抽象类中!
     * 思考:
     * 1.new 抽象类的子类,原抽象类中存在构造器吗?
     * 存在构造器,而且如果new 子类的一个对象会先调用抽象类的构造器,然后调用子类的构造器
     * 2.抽象类存在的意义是什么?
     * 抽象类有很多的抽象方法,子类必须根据自己的要求重写这些抽象方法,而不同于抽象类的普通方法
     */
}
package com.oop.demo10;

public class B extends Action {
    //抽象类的所有抽象方法,继承了它的子类,都必须要实现~除非该类又是一个抽象类

    public B(){
        System.out.println("B 的构造器");
    }
    @Override
    public void doSomething() {
        System.out.println("BdoSomething");
    }

    @Override
    public void print() {
        System.out.println("Bprint");
    }

}
package com.oop.demo10;

public class A extends Action{
    //抽象类的所有抽象方法,继承了它的子类,都必须要实现~除非该类又是一个抽象类

    public A(){
        System.out.println("A 的构造器");
    }
    @Override
    public void doSomething() {
        System.out.println("AdoSomething");
    }

    @Override
    public void print() {
        System.out.println("Aprint");
    }
}
package com.oop.demo10;

public class Test {
    public static void main(String[] args) {
        A a = new A();          //a属于A类
        a.doSomething();        //a调用子类重写抽象类的抽象方法
        B b = new B();          //B属于B类
        b.doSomething();        //b调用子类重写抽象类的抽象方法
        Action a1 = new A();    //a1属于A类
        a1.print();             //a1调用子类重写抽象类的方法(多态)
        Action b1 = new B();    //b1属于B类
        b1.print();             //b1调用子类重写抽象类的方法(多态)
        b1.run();               //b1调用继承父类的方法
        b1.setName("B");        //name属于Action类的私有属性,故只能采用封装的思想使用
        System.out.println(b1.getName());
    }
}

接口的定义和实现

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范!以自己无法写方法~专业的约束! 约束和实现分离:面向接口编程~
  • 接口就是规范,定义的是一组规则,体现了现实世界中"如果你是...则必须能..."的思想
  • 接口的本质是契约,就像人间的法律一样,如果制定,必须遵守
  • OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么讨论设计模式都只针对具备抽象能力的语言(比如C++,Java,C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象
package com.oop.demo11;

public interface TimeService {
    void timer();
}
package com.oop.demo11;

//interface 定义的关键字
public interface UserService {
    //常量:public static final
    int AGE = 99;
    //接口中的所有定义其实都是抽象的 public abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}
package com.oop.demo11;

//抽象类:extends~
//类 可以实现接口 implements 接口
//实现了接口的类,就要重写接口中的方法~
//利用接口实现了多继承
public class UserServiceImpl implements UserService,TimeService{

    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}

接口的作用

1.约束,只能规范

2.接口中定义的方法:public abstract

3.接口中定义的属性:public static final

4.接口不能被实例化,接口不是类没有构造方法

5.implements 可以实现多个接口

6.一旦继承了接口,必须要重写接口中的方法

N种内部类

成员内部类、静态内部类

  1. 成员内部类:外部类里包含一个内部类,直接加载内部类(可以获得外部类的私有属性)解决一些问题(封装)
  2. 静态内部类:外部类里包含一个内部类,直接加载内部类(不可以获得外部类的私有属性)解决一些问题(封装)
package com.oop.demo12;

public class Outer {
    private int id = 10086;
    public void out(){
        System.out.println("外部类方法");
    }
    //成员内部类
    //public static Inner{} 静态内部类 -> 无法使用外部类的非静态属性
    public  class Inner{
        public void in(){
            System.out.println("内部类方法");
        }
        //可以获得外部类的私有属性
        public void getID(){
            System.out.println(id);
        }
    }
}
package com.oop.demo12;

public class Aplication {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.out();
        //通过外部类Outer来实例化内部类Inner
        Outer.Inner inner = outer.new Inner();
        inner.in();
        inner.getID();

    }
}

局部内部类、匿名内部类

  1. 匿名内部类:加载类的方法,使用局部内部类解决问题(封装细节)
/*局部内部类*/
package com.oop.demo13;

public class Outer {

    public void method(){
        //局部内部类
        class Inner{
            public void in(){
                System.out.println("局部内部类");
            }
        }

        Inner inner = new Inner();
        inner.in();
    }
}
package com.oop.demo13;

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.method();

    }
}

  1. 匿名内部类:节省空间
/*匿名内部类*/
package com.oop.demo14;

public class Outer {
    public static void main(String[] args) {
        //没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();
        UserService userService = new UserService(){
            @Override
            public void hello() {
                System.out.println("hello");
            }
        };
        userService.hello();

    }
}

//匿名内部类
class Apple{
    public void eat(){
        System.out.println("eat Apple");
    }
}
//匿名内部接口
interface UserService{
    void hello();
}

异常

捕获和抛出异常

  1. 异常处理机制
  • 抛出异常
  • 捕获异常
  1. 异常处理五个关键字
  • try、catch、finally、throw、throws
package com.exception;

public class Demo01 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {                               // try监控区域
            System.out.println(a/b);
        }catch (ArithmeticException e){     //catch 捕获异常
            System.out.println("程序出现异常,变量b不能为0");
        }finally {                          //finally可以不要,假设I/O,资源出现异常,可以使用finally关闭
            System.out.println("finally");
        }


    }
}
package com.exception;

public class Demo02 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        //假设要捕获多个异常,从小到大!
        try {
            Demo02 demo02 = new Demo02();
            demo02.a();
        }catch (Exception e){
            System.out.println("Exception");
        }catch (Error e){
            System.out.println("Error");
        }catch (Throwable e){
            System.out.println("Throwable");
        }finally {
            System.out.println("finally");
        }
    }
    public void a(){b();}
    public void b(){a();}
}
package com.exception;

public class Demo03 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        //选中要监控的代码 Ctrl + Alt + T
        try {
            System.out.println(a/b);
        } catch (Exception e) {
            e.printStackTrace(); //打印错误的栈信息
        } finally {              // finally处理善后信息
        }


    }
}
package com.exception;

public class Demo04 {
    public static void main(String[] args) {
        new Demo04().test(1,0);
    }

    public void test(int a,int b){
        if (b==0){  //throw
            throw new ArithmeticException();//主动抛出异常,一般在方法中使用
        }
    }
}
package com.exception;

public class Demo05 {
    public static void main(String[] args) {
        new com.exception.Demo04().test(1,0);
    }
    //假设这个方法中,处理不了这个异常,就在方法上抛出异常
    public void test(int a,int b) throws ArithmeticException {}
}

自定义异常及经验小结

package com.exception.finaldemo;

//定义的异常类
public class MyException extends Exception{
    //传递数字10;
    private int detail;

    public MyException(int a){
        this.detail = a;
    }

    //返回异常的信息
    @Override
    public String toString() {
        return "MyException{" + detail + '}';
    }

}
package com.exception.finaldemo;

public class Test {
    //可能会存在异常的方法
    public static void test(int a)throws MyException{
        System.out.println("传递的参数为:"+a);
        if (a>10){
            //在这个方法中处理不了这个异常,,就在方法上抛出异常
            throw new MyException(a);
        }
        System.out.println("ok!");
    }

    public static void main(String[] args) {
        try {
            test(20);
        } catch (MyException e) {
            //增加一些处理异常的代码
            System.out.println(e);
        }
    }
}

posted @ 2024-03-05 20:16  qing集  阅读(1)  评论(0编辑  收藏  举报