Java面向对象特性总结

1.面对对象与面对过程的区别

什么是封装?我看到过这样一个例子:

我要用洗衣机洗衣服,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内 部的结构吗?有必要碰电动机吗?有必要了解如何通电的吗?

如果是对于面向过程来说,这些你都得知道。“吾生也有涯,而知也无涯”,面向对象的封装与庄子的思想遥相呼应:用有限的时间去做更适合的事情。

面对过程是软件开发的先驱者,但其局限性不能满足当今的主流市场需求。

  • 面对过程注重微观,每一步都亲力亲为;面对对象注重宏观,更加偏向于整体的流程。
  • 性能:面对过程执行效率更高。Java是编译成字节码给JVM运行,而面向过程直接编译成机器码执行
  • 复用性:面对对象的封装,继承极大的扩展了代码的复用性

2.面对对象特征——封装

封装的核心思想是隐藏实现,暴露接口

封装的目的:

  • 解耦(符合迪米特法则)
  • 保护数据安全(通过getter方法来获取类中属性值)

  • 访问权限修饰符

修饰符 | 权限范围

public | 本类,子类,本包,外部包

protected | 本类,子类,本包

default | 本类,子类

private | 本类

3.面对对象特征——继承

继承主要目的是实现代码复用。

特性:

  • 子类具有父类非private的属性和方法
  • 子类可以扩展自己的属性和方法

构造器的继承问题

  • 构造器是不会被子类继承的,但子类的对象在初始化时会默认调用父类的无参构造器
  • 当父类显示写了有参构造器,且没有无参构造器。子类继承父类的时候必须显示的调用父类的有参构造器。调用的方式可以使用super(a,b)来调用。

static修饰符的继承问题

子类是不会继承父类被static修饰的方法和变量,但是可以调用。

super 与 this 关键字

super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

this关键字:指向自己的引用。

final关键字

final 关键字声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

  • 方法不能重写
  • 类不能继承
  • final标记的变量(成员变量或局部变量)即称为常量。名称大写,且只 能被赋值一次。

子类对象实例化过程

new出一个子类对象的时候,必须先new出一个父类对象。子类在调用构造方法时,会先调用父类的构造方法。(默认)

如果不写构造方法,编译器默认加上一个无参构造器。如果写了构造器,编译器不会添加。

如果写了有参构造器,子类就必须调用父类的构造方法。super(参数)。

如果同时有有参和无参构造器,那么会默认调用无参。也可以自定义调用有参。

4.面对对象特征——多态

提高了代码的通用性。

多态分为编译时多态(方法重载)和运行时多态(方法重写)。

  • 重载与重写

重写指子类重写父类的方法,方法名、参数列表必须相同,返回值范围小于等于父类抛出的异常范围小于等于父类访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private或者final 则子类就不能重写该方法。

重载发生在同一个类中,方法名必须相同参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。

  • 向上转型

在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。

  • 强制转换 从子类到父类的类型转换可以自动进行 从父类到子类的类型转换必须通过造型(强制类型转换)实现 无继承关系的引用类型间的转换是非法的

5.Object类

  • Object类是所有Java类的根父类
  • 如果在类的声明中未使用extends关键字指明其父类,则默认父类 为java.lang.Object类(任何类都可以调用Object的方法)
package java.lang;


public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }

   
    public final native Class<?> getClass();

   
    public native int hashCode();

    public boolean equals(Object obj) {
        return (this == obj);
    }

    protected native Object clone() throws CloneNotSupportedException;

   
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

   
    public final native void notify();

   
    public final native void notifyAll();

  
    public final native void wait(long timeout) throws InterruptedException;

    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

    public final void wait() throws InterruptedException {
        wait(0);
    }

   
    protected void finalize() throws Throwable { }
}

Object的主要组成:

  • public native int hashCode(); 取得hash码
  • equals(Object obj) 比较对象
  • clone() 可用于复杂对象的深拷贝

==与equals的区别

== 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型 就是比较内存地址。

equals的话,,如果该方法没有被重写过默认等同于==;

但是很多类默认重写了:(比如String)

6.包装类的使用

装箱:基本数据类型--->包装类

拆箱:包装类--->基本数据类型

//装箱
Integer t = new Integer(500);

//float  to Float
Float f = new Float(“4.56”);

//拆箱
Integer x = 3;
int i  =  x.intValue();


//int to String 
String str = String.valueOf(1);

//String to int
int x = Integer.parseInt(str1) ;

//包装类  to String
Integer x = 8;
String str = x.toString();

or

String str = Integer.toString(3);

7.static关键字

在Java类中,可用static修饰属性、方法、代码块、内部类。

被修饰后的成员具备以下特点:

  • 修饰的成员,被所有对象所共享
  • 访问权限允许时,可不创建对象,直接用类名.属性或方法调用

在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。

static修饰的方法不能被重写

static的应用:单例模式——静态内部类

class StaticClassInner {
private StaticClassInner() {}
/*
使用静态内部类,实现了延迟加载
调用getInstance()方法时,才会加载StaticClassInnerInstance。
通过JVM类加载线程安全的机制,避免了线程不安全。
*/
private static class StaticClassInnerInstance {
private static final StaticClassInner INSTANCE = new StaticClassInner();
}
public static StaticClassInner getInstance() {
return StaticClassInnerInstance.INSTANCE;
}
}
public class Operation
{
public static void main(String[] args) {
StaticClassInner doubleCheck1 = StaticClassInner.getInstance();
StaticClassInner doubleCheck2 = StaticClassInner.getInstance();
System.out.println(doubleCheck1.hashCode());
System.out.println(doubleCheck2.hashCode());
}
}

8.代码块

对类或对象进行初始化。

代码块可分为静态代码块和非静态代码块。(有无static修饰)

静态代码块:用static修饰的代码块

  1. 可以有输出语句。
  2. 可以对类的属性、类的声明进行初始化操作。
  3. 不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
  4. 若有多个静态的代码块,那么按照从上到下的顺序依次执行。
  5. 静态代码块的执行要先于非静态代码块。
  6. 静态代码块随着类的加载而加载,且只执行一次。

非静态代码块:没有static修饰的代码块

  1. 可以有输出语句。
  2. 可以对类的属性、类的声明进行初始化操作。
  3. 除了调用非静态的结构外,还可以调用静态的变量或方法。
  4. 若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
  5. 每次创建对象的时候,都会执行一次。且先于构造器执行。

9.抽象类和抽象方法

  • 用abstract关键字来修饰一个类,这个类叫做抽象类。
  • 用abstract来修饰一个方法,该方法叫做抽象方法。

10.interface

  • 用interface来定义。
  • 接口中的所有成员变量都默认是由public static final修饰的。
  • 接口中的所有抽象方法都默认是由public abstract修饰的。
  • 接口中没有构造器。
  • 接口采用多继承机制。

定义Java类的语法格式:先写extends,后写implements

class SubClass extends SuperClass implements InterfaceA{ }

接口和抽象类之间的对比

11.内部类

在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者 称为外部类。

Inner class的名字不能与包含它的外部类类名相同;

成员内部类(static成员内部类和非static成员内部类)

class Outer {
    private int s;
    public class Inner {
    public void mb() {
        s = 100;
        System.out.println("在内部类Inner中s=" + s);
    }
   }
    public void ma() {
        Inner i = new Inner();
        i.mb();
    } }
public class InnerTest {
    public static void main(String args[]) {
        Outer o = new Outer();
        o.ma();
} }

局部内部类(不谈修饰符)

class 外部类{
    方法(){
    class 局部内部类{ } 
    }
    {class 局部内部类
    { }
    }
}
  • 只能在声明它的方法或代码块中使用,而且是先声明后使用。除此之外的任何地方 都不能使用该类
  • 但是它的对象可以通过外部方法的返回值返回使用,返回值类型只能是局部内部类 的父类或父接口类型
  • 局部内部类可以使用外部方法的局部变量,但是必须是final的。

匿名内部类

匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一 个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或 实现一个类。

匿名内部类的特点

  • 匿名内部类必须继承父类或实现接口
  • 匿名内部类只能有一个对象
  • 匿名内部类对象只能使用多态形式引用
interface A{
public abstract void fun1();
}
public class Outer{
    public static void main(String[] args) {
        new Outer().callInner(new A(){
//接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为对象取名
        public void fun1() {
            System.out.println(“implement for fun1");
        }
    });// 两步写成一步了
}
        public void callInner(A a) {
                a.fun1();
        }
}

12.异常处理

异常:在Java语言中,将程序执行中发生的不正常情况称为“异常”。

(开发过程中的语法错误和逻辑错误不是异常)

Java程序在执行过程中所发生的异常事件可分为两类:

  • Error:Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源 耗尽等严重情况。一般不编写针对性 的代码进行处理。
  • Exception: 其它因编程错误或偶然的外在因素导致的一般性问题,可以使 用针对性的代码进行处理。

异常处理机制一: try-catch-finally

在编写程序时,经常要在可能出现错误的地方加上检测的代码, 如进行x/y运算时,要检测分母为0,数据为空,输入的不是数据 而是字符等。过多的if-else分支会导致程序的代码加长、臃肿, 可读性差。因此采用异常处理机制。

  • Java程序的执行过程中如出现异常,会生成一个异常类对象, 该异常对象将被提交给Java运行时系统,这个过程称为抛出 (throw)异常。
  • 如果一个方法内抛出异常,该异常对象会被抛给调用者方法中处 理。如果异常没有在调用者方法中处理,它继续被抛给这个调用 方法的上层方法。这个过程将一直继续下去,直到异常被处理。 这一过程称为捕(catch)异常。
  • 程序员通常只能处理Exception,而对Error无能为力。

异常处理是通过try-catch-finally语句实现的。

 try{
 ...... //可能产生异常的代码
 }
 catch( ExceptionName1 e ){
 ...... //当产生ExceptionName1型异常时的处置措施
 }
 catch( ExceptionName2 e ){
 ...... //当产生ExceptionName2型异常时的处置措施
 }
 [ finally{
 ...... //无论是否发生异常,都无条件执行的语句
 } ]
  • 如果抛出的异常是IOException等类型的非运行时异常,则必须捕获,否则 编译错误。也就是说,我们必须处理编译时异常,将异常进行捕捉,转化为 运行时异常

异常处理机制二: throws

  • 如果一个方法(中的语句执行时)可能生成某种异常,但是并不能确定如何处理这 种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理, 而由该方法的调用者负责处理
  • 在方法声明中用throws语句可以声明抛出异常的列表,throws后面的异常类型可 以是方法中产生的异常类型,也可以是它的父类。
  • 重写方法不能抛出比被重写方法范围更大的异常类型。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券