java se复习 day 1

一、面向对象的特性

1.1 继承

获得已有类的特性去创建新的类

1.2 封装

把数据和对数据的操作隐藏起来,对外提供特定的访问数据的接口

1.3 多态

  • 编译时多态性,又称前绑定
    方法重载,就是一个类中允许存在同名的方法,但是前提是同名方法的参数类型或者参数个数不同。在实现类似功能,但需要的参数个数等不同时,可以使用方法重载。
  • 运行时多态性,又称后绑定
    方法重写:子类继承并重写父类的方法或者抽象方法。
    对象造型:父类引用指向子类对象,这样调用同一个方法时,会因为子类对象的不同,而产生不同的结果。这样的好处是,让你更多的去关注父类需要实现的是什么功能,而不是关注这个功能时怎么实现的。
  • 注意
    重写的概念只针对方法,对属性进行重写时,编译时会报错。

1.4 抽象

将一类事物的共同特征提取出来,只关注对象的属性和行为,而不去关注具体的细节是怎么实现的。

  • 数据抽象
  • 行为抽象

二、权限修饰符

2.1 权限修饰符

在这里插入图片描述
当子类对象上转型为父类对象时,不论子类中有没有定义这个静态方法,该对象都会使用父类中的静态方法。

2.2 clone对象

2.2.1 clone概念

当我们需要一个对象的副本,且副本的改变不会影响到原对象的改变,我们可以使用clone方法。 Object对象有个clone()方法,实现了对象中各个属性的复制,但它的可见范围是protected的,所以实体类使用克隆的前提是:

① 实现Cloneable接口,这是一个标记接口,自身没有方法。

② 覆盖clone()方法,可见性提升为public。

2.2.2 浅拷贝

只将基本类型数据进行拷贝,引用类型数据只是简单的复制引用


@Data
public class A implements Cloneable{
    private String name;
    private String address;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class TestA {
    public static void main(String[] args) throws CloneNotSupportedException {
        A a = new A();
        a.setName("张三");
        a.setAddress("北京");
        Object clone = a.clone();
        A b = (A)clone;
        System.out.println("a:" + a);
        b.setName("李四");
        System.out.println("b:"+ b);
    }
}

结果:
a:A(name=张三, address=北京)
b:A(name=李四, address=北京)

2.2.3 深拷贝

基本类型数据和引用类型数据都进行拷贝,如果想要深拷贝一个对象,这个对象必须要实现 Cloneable 接口,实现 clone
方法,并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份,这就要求这个被引用的对象必须也要实现
Cloneable 接口并且实现 clone 方法


@Data
public class A implements Cloneable{
    private String name;
    private address add;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object clone = super.clone();
        A clone1 = (A) clone;
        address add = clone1.getAdd();
        clone1.setAdd((address)add.clone());
        return clone;
    }
}
@Data
public class address implements Cloneable{
    private String street;
    private String ID;

    public address(String street, String ID) {
        this.street = street;
        this.ID = ID;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

结果:

A(name=张三, add=address(street=北京, ID=31号))
A(name=张三, add=address(street=上海, ID=32号))

2.3 new对象和clone对象的区别

都是分配内存,new对象是根据new后面类型来决定分配空间的大小,clone是和原对象分配的空间一样大。

2.4 &与&&

  • &&短路与,左边false,右边不进行运算。
  • &整体需要运算

2.5 跳出多重嵌套循环

给一个标志位,跳出标志位计即可

public class break_while {
    public static void main(String[] args) {
        a:for (int i = 0; i < 10; i++) {
            System.out.println("你好");
            if(i > 4)
                break a;
        }
    }
}

三、equals方法

3.1 equals与hashcode

  • 如果两个对象相同(equals 方法返回 true),那么它们的 hashCode 值一定要相同;
  • 如果两个对象的 hashCode 相同,它们并不一定相同。

3.2 equals方法需满足的特性

  • 自反性(x.equals(x)必须返回 true)
  • 对称性(x.equals(y)返回 true 时, y.equals(x)也必须返回 true)
  • 传递性(x.equals(y)和 y.equals(z)都返回 true 时, x.equals(z)也必须返回 true)
  • 一致性(当x 和 y 引用的对象信息没有被修改时,多次调用 x.equals(y)应该得到同样的返回值)
  • 对于任何非 null 值的引用 x, x.equals(null)必须返回 false。

equals方法:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

  1. 使用==操作符检查"参数是否为这个对象的引用";
  2. 使用 instanceof 操作符检查"参数是否为正确的类型"

3.3 string

string是final类,不能被继承,对 String 类型最好的重用方式是关联关系(Has-A)和依赖关系(UseA)而不是继承关系(Is-A)。

3. 4 Java 语言的方法调用

Java 语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。

3.5 重写和重载

  • 重载

1.方法名一致,参数列表中参数的顺序,类型,个数不同。
2.重载与方法的返回值无关,存在于父类和子类, 同类中。
3.可以抛出不同的异常,可以有不同修饰符。

  • 重写

1.参数列表必须完全与被重写方法的一致,返回类型必须完全与被重写方法的返回类型一致。
2.构造方法不能被重写,声明为 final 的方法不能被重写,声明为 static 的方法不能被重写,但是能够被再次
声明。
3.访问权限不能比父类中被重写的方法的访问权限更低。
4.重写的方法能够抛出任何非强制异常(UncheckedException,也叫非运行时异常),无论被重写的方法是
否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则
可以

四、一些面试题

4.1 为什么函数不能根据返回类型来区分重载

我们一般调用函数时,有可能不指定函数的结果由什么样类型的参数接收,如直接调用某个方法,max(a,b),当有方法重载时,不知道该返回那种类型的结果。

4.2 抽象类和接口异同

  • 抽象类
    1.抽象类中可以定义构造器
    2.可以有抽象方法和具体方法
    3.接口中的成员全都是 public 的
    4.抽象类中可以定义成员变量
    5.有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法
    6.抽象类中可以包含静态方法
    7.一个类只能继承一个抽象类

  • 接口
    1.接口中不能定义构造器
    2.方法全部都是抽象方法
    3.抽象类中的成员可以是 private、默认、 protected、 public
    4.接口中定义的成员变量实际上都是常量
    5.接口中不能有静态方法
    6.一个类可以实现多个接

  • 相同点
    1.不能够实例化
    2.可以将抽象类和接口类型作为引用类型
    3.一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要
    被声明为抽象类

4.3 抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized

都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如 C 代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。 synchronized 和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

4.4 阐述静态变量和实例变量的区别?

  • 静态变量: 是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不 管创建多少个对象,静态变量在内存中有且仅有一个拷贝;
  • 实例变量: 必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。

4.5 ==和 equals 的区别?

equals 和== 最大的区别是一个是方法一个是运算符。
==:如果比较的对象是基本数据类型,则比较的是数值是否相等;如果比较的是引用数据类型,则比较的是对象
的地址值是否相等。
equals():用来比较方法两个对象的内容是否相等。
注意: equals 方法不能用于基本数据类型的变量,如果没有对 equals 方法进行重写,则比较的是引用类型的变
量所指向的对象的地址。

4.6 break 和 continue 的区别?

break 和 continue 都是用来控制循环的语句。
break 用于完全结束一个循环,跳出循环体执行循环后面的语句。
continue 用于跳过本次循环,执行下次循环。

4.7 String s = “Hello”;s = s + " world!";这两行代码执行后,原始的 String 对象中的内容到底变了没有?

没有。因为 String 被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中, s 原先指向一个 String 对象,内容是 “Hello”,然后我们对 s 进行了“+” 操作,那么 s 所指向的那个对象是否发生了改变呢?答案是没有。这时, s 不指向原来那个对象了,而指向了另一个 String 对象,内容为"Hello world!",原来那个对象还 存在于内存之中,只是 s 这个引用变量不再指向它了。

4.8 new和不new String对象的区别

使用内容相同的字符串,不new,使用的是存在的字符串,new,会调用构造器,生成新对象,使内存开销增大。

public class TestA {
    public static void main(String[] args) throws CloneNotSupportedException {
        String a = "hello";
        String b = "hello";
        String c = new String("hello");
        String d = new String("hello");
        System.out.println(a == b);
        System.out.println(a == c);
        System.out.println(c == d);
    }
}

结果:

true
false
false

4.9 不可变类的优缺点

可变类有一些优点,比如因为它
的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来
代表,可能会造成性能上的问题。所以 Java 标准类库还提供了一个可变版本,即 StringBuffer。

五、java中的多态

5.1 Java 中实现多态的机制是什么?

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动
态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变
量的类型中定义的方法。

5.2 程序绑定

绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定.

5.3 静态绑定

参考:https://blog.csdn.net/zhangjk1993/article/details/24066085
在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中的方法),此时由编译器或其它连接程序实现。针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定。

5.4 动态绑定

后期绑定:在运行时根据具体对象的类型进行绑定。
若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。

动态绑定过程:
虚拟机提取对象的实际类型的方法表;
虚拟机搜索方法签名;
调用方法。

5.5 将方法声明为final类型

一是为了防止方法被覆盖,二是为了有效地关闭java中的动态绑定)。
静态绑定是有很多的好处,它可以让我们在编译期就发现程序中的错误,而不是在运行期。这样就可以提高程序的运行效率!而对方法采取动态绑定是为了实现多态,多态是java的一大特色。多态也是面向对象的关键技术之一,所以java是以效率为代价来实现多态这是很值得的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值