面对对象

面向对象

面向对象的本质就是:以类的方式组织代码,以 对象的方式封装数据

new关键字

  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认初始化以及调用构造方法

构造方法

创建对象的时候自动调用(无参构造),主要作用是为了初始化

  • 必须和类的名字相同
  • 必须没有返回值,不能写void

构造方法的重载

  • 构造方法重载成有参构造之后,如果还需要使用无参构造,必须重新建里无参构造
在IDEA中使用快捷键alt+insert可以快速添加重载构造方法以及get,set方法

静态方法和非静态方法

  • 静态方法:用static修饰,可以直接类名.方法进行调用,从属于类,和类一起加载。
  • 非静态方法:没有用static进行修饰,调用时必须创建对象,从属于对象,和对象一起加载。
  • 静态方法在访问本类的成员时只允许方法问静态成员(静态方法和静态成员变量),不能访问对非静态成员变量和非静态成员方法。而非静态方法可以访问本类的静态成员。主要原因是因为,静态方法是和类一起加载的,非静态方法是和对象一起加载的,对象就是类的实例化,因此在没有实例化之前是无法调用非静态成员的,所以静态方法无法调用非静态成员,同时非静态方法又称为实例方法。

封装

  • 高内聚,低耦合——程序设计需要追求高内聚,低耦合。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉。低耦合仅暴露少量的方法给外部使用。

  • 封装:应禁止直接访问一个对象中数据的实际表现,而应通过操作接口来访问,这成为信息隐藏。

  • 属性私有,get/set方法

封装的作用

  1. 提高程序的安全性,保护数据
  2. 隐藏代码的实现细节
  3. 统一接口
  4. 系统可维护增加了

继承

  • Java中只有单继承是没有多继承的
  • 继承是类和类之间的一种关系。除了继承之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends表示
  • 子类和父类的关系,Student继承自Person,Student是Person的子类
  • final修饰的类无法继承
public class Person{
}
//Student继承父类Person
public class Student extends Person{
}
  • 子类会拥有父类的方法和属性,但是不会继承私有方法和属性
  • 在Java中所有的类都直接或者间接继承Object

父类和子类的构造方法以及super详解

//调用父类的构造方法必须卸载子类的构造方法的第一行
public class Person{
	public Person() {
        System.out.println("Person");
    }
}
//Student继承父类Person
public class Student extends Person{
    public Student(){
        //这里隐藏了super(),会调用父类的无参构造
        //super();
        System.out.println("Student");
        //不能在这里调用父类构造方法super()
	}
}

//若父类只有有参构造,那么子类就无法使用父类无参构造,必须在子类的无参构造中写出父类有参构造
public class Person{
    //这里写了有参构造,无参构造就没了,需要重新写无参构造
	public Person(String name) {
        System.out.println("Person");
    }
}
//Student继承父类Person
public class Student extends Person{
    //这里会报错,因为父类是有参构造,子类是无参构造,必须要写出父类的有参构造
    public Student(){
        //这里隐藏了super(),会调用父类的无参构造
        //super();
        super("name");
        System.out.println("Student");
        //不能在这里调用父类构造方法super()
	}
}

super必须只能出现在子类的方法或者构造方法中。

super和this不能同时调用构造方法。

  • this:本身调用者这个对象。super:代表父类对象的引用
  • this:没有继承也可以使用。super:只能在继承条件才可以使用
  • this();本类的构造。super();父类的构造

方法的重写

方法重写和重载完全不同,重载是同类中,方法名相同,参数类型不同,而重写是子类重写父类方法,方法名相同,参数类型相同,修饰符范围可以扩大但是不能缩小,抛出的异常范围可以缩小但是不能扩大。

//静态成员可以被继承,但是不会被重写,如果子类有同名的静态成员,那么父类的静态成员会被隐藏
public class A {
    static String str = "A静态成员";
    String str1 = "A非静态成员";

    static public void staticPrint() {
        System.out.println("A静态方法");
    }
    public void print() {
        System.out.println("A非静态方法");
    }
}
public class B extends A{
    static String str = "B静态成员";
    String str1 = "B非静态成员";

    static public void staticPrint() {
        System.out.println("B静态方法");
    }
    public void print() {
        System.out.println("B非静态方法");
    }
}
public class C extends A{
}

//主函数
public static void main(String[] args) {
    C c = new C();
    System.out.println(c.str);
    System.out.println(c.str1);
    c.staticPrint();
    c.print();
	//A静态成员
	//A非静态成员
	//A静态方法
	//A非静态方法

    A b = new B();
    System.out.println(b.str);
    System.out.println(b.str1);
    b.staticPrint();
    b.print();
    //B静态成员
	//B非静态成员
	//B静态方法
	//B非静态方法

}

为什么需要重写

  • 父类的功能,子类不一定需要或者不一定满足!

多态

一种方法可以根据发送对象的不同而采用多种不同的行为方式。

多态存在的条件

  • 有继承关系
  • 子类重写父类方法
  • 父类引用指向子类对象
  • 多态是方法的多态,属性没有多态
//People类
public class People {
    public void eat() {
        System.out.println("吃饭");
    }
}
//学生类
public class Student extends People{
    @Override
    public void eat() {
        System.out.println("吃水煮肉片");
    }

    public void study() {
        System.out.println("学习");
    }
}
//测试
public class Demo05 {
    public static void main(String[] args) {
        People p = new Student();
        p.eat();//输出水煮肉片
        ((Student) p).study();//要调用study()方法需要转换p的类型

    }
}

instanceof关键字

用来判断对象和类之间的继承关系

//Person->Student
//Person->Teacher
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof People );//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
People people = new Student();
System.out.println(people instanceof Student);//true
System.out.println(people instanceof People );//true
System.out.println(people instanceof Object);//true
System.out.println(people instanceof Teacher);//false
//System.out.println(people instanceof String);//编译报错,因为People和String都是继承Student的

子类和父类的转换

  • 父类引用指向子类的对象
  • 把子类转换为父类,向上转型
  • 把父类转换成子类,向下转型,强制转换
  • 方便方法的调用,减少重复的代码!
//子类转换成父类,可能会丢失自己本来的一些方法
//父 					子
Person student = new Student();
//强制转化,将父类转成子类
Student s = (Student) student;

抽象类

  • abstract修饰的类称为抽象类
  • abstract修饰的方法称为抽象方法
  • 子类继承抽象类,必须重写抽象类中的所有抽象方法
  • 不能new这个抽象类,只能靠子类去实现它。但是抽象类有构造器,只是不能直接创建抽象类的实例对象。在继承抽象类的子类中通过super()可以调用抽象类中的构造方法
  • 抽象类中可以写普通方法
  • 抽象方法必须在抽象类中
  • 抽象类存在的意义:更利于代码的维护和重用

接口(真的很关键)

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范!自己无法写方法专业的约束约束和实现分离,面向接口编程
  • 接口中的所有定义方法都是抽象的public abstract,所有的变量都定义成常量public static final
  • 接口可以用implements继承多个接口

内部类

内部类就是在一个类的内部定义了一个类。比如,A类中定义了一个B类,那么B类相对于A类来说称为内部类,而A类相对于B类来说就是外部类了

  • 成员内部类
public class Outer {
    private int id = 10;
    public void out() {
        System.out.println("这是外部类方法");
    }
    //成员内部类用static修饰之后无法调用外部类的非静态成员
    class Inner{
        public void in(){
            System.out.println("这是内部类方法");
        }
        public void getID(){
            System.out.println(id);
        }
    }
}

public class Demo10 {
    public static void main(String[] args) {

        Outer outer = new Outer();
        //通过外部类来实例化内部类~
        Outer.Inner inner = outer.new Inner();
        inner.getID();
    }
}

一个Java文件中可以有多个class类,但是只能有一个public类

  • 局部内部类
public class LocalInnerClass {
    public static void main(String[] args) {

        //定义局部内部类
        class InnerBase{
            int a;
        }
        class  InnerSub extends InnerBase {
            int b;
        }

        InnerSub is = new InnerSub();
        is.a = 1;
        is.b = 2;
        System.out.println("a = "+ is.a + " b = "+ is.b);
    }
}
  • 匿名内部类
public class Demo10 {
    public static void main(String[] args) {

        //匿名对象
        new Apple().eat();
        //匿名内部类
        //一般格式, new 类名/抽象类/接口(){};
        new UserService(){
			//重写接口中的方法
        }
    }
}

class Apple{
    public void eat(){
        System.out.println("1");
    }
}

异常

  • 异常处理五个关键词try,catch,finally,throw,throws
public class Demo01 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        //多个catch捕获异常必须要从小到大
        try {
            System.out.println(a/b);
        }catch(ArithmeticException e) {//想要捕获的异常类型,最高级别异常类型Throwable
            System.out.println("被除数不能为0");
            e.printStackTrace();//打印当前异常错误信息
        }finally{
            System.out.println("finally");//无论是否捕获到异常都会运行
            //finally可以不需要
        }
    }
}
  • 抛出异常
//方法体内抛出异常throw
public class Demo02 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        try {
            if (b == 0) {
                throw new ArithmeticException();//主动抛出异常
            }
            System.out.println(a/b);
        }finally{
            System.out.println("finally");
        }
    }
}

//方法抛出异常
public static void main(String[] args) {
    int a = 1;
    int b = 0;

    try {
        new Demo02().test(1,0);
    }catch(ArithmeticException e) {
        System.out.println("被除数不能为0");
    }finally{
        System.out.println("finally");
    }
}
public void test(int a, int b) throws ArithmeticException{
    System.out.println(a/b);
}

自定义异常

public class MyException extends Exception{

    //传递数字>10
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }
    //toString:异常的打印信息

    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

public class Test {
    //可能会存在异常的方法

    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(11);
        } catch (MyException e) {
            System.out.println("MyException=>"+e);
        }
    }
}

实际应用中的经验总结

  • 在多重catch后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以假设try-catch,处理潜在的异常
  • 尽量去处理异常,切记简单地调用printStackTrace()打印输出
  • 尽量添加finally语句块去释放占用资源
posted @ 2020-05-11 10:04  GoodForNothing  阅读(202)  评论(0编辑  收藏  举报
//看板娘