Java进阶 ——— 面试常见问题

1. java中==和equals和hashCode的区别

  • 1.关系操作符“==”到底比较的是什么?

“关系操作符生成的是一个boolean结果,它们计算的是操作数的值之间的关系”。

  这句话看似简单,理解起来还是需要细细体会的。说的简单点,==就是用来比较值是否相等
在Java中游8种基本数据类型:

  浮点型:float(4 byte), double(8 byte)

  整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)

  字符型: char(2 byte)

  布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值”true”和”false”)

  对于这8种基本数据类型的变量,变量直接存储的是“值”,因此在用关系操作符==来进行比较时,比较的就是 “值” 本身。要注意浮点型和整型都是有符号类型的,而char是无符号类型的(char类型取值范围为0~2^16-1).

  也就是说比如:

  int n=3;

  int m=3; 

  变量n和变量m都是直接存储的”3”这个数值,所以用==比较的时候结果是true。

  • 2.equals比较的又是什么?

equals方法是基类Object中的方法,因此对于所有的继承于Object的类都会有该方法。为了更直观地理解equals方法的作用,直接看Object类中equals方法的实现。

下面是String类中equals方法的具体实现:
String中equals

 可以看出,String类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。

  其他的一些类诸如Double,Date,Integer等,都对equals方法进行了重写用来比较指向的对象所存储的内容是否相等。

  • 3.关于hashCode()

这个方法返回对象的散列码,返回值是int类型的散列码。
对象的散列码是为了更好的支持基于哈希机制的Java集合类,例如 Hashtable, HashMap, HashSet 等。

关于hashCode方法,一致的约定是:
重写了euqls方法的对象必须同时重写hashCode()方法。

如果2个对象通过equals调用后返回是true,那么这个2个对象的hashCode方法也必须返回同样的int型散列码

如果2个对象通过equals返回false,他们的hashCode返回的值允许相同。(然而,程序员必须意识到,hashCode返回独一无二的散列码,会让存储这个对象的hashtables更好地工作。)

相比 于 equals公认实现约定,hashCode的公约要求是很容易理解的。有2个重点是hashCode方法必须遵守的。约定的第3点,其实就是第2点的
细化,下面我们就来看看对hashCode方法的一致约定要求。

第一:在某个运行时期间,只要对象的(字段的)变化不会影响equals方法的决策结果,那么,在这个期间,无论调用多少次hashCode,都必须返回同一个散列码。

第二:通过equals调用返回true 的2个对象的hashCode一定一样。

第三:通过equasl返回false 的2个对象的散列码不需要不同,也就是他们的hashCode方法的返回值允许出现相同的情况。

总结一句话:等价的(调用equals返回true)对象必须产生相同的散列码。不等价的对象,不要求产生的散列码不相同。


总结来说:

  1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;

    如果作用于引用类型的变量,则比较的是所指向的对象的地址

  2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量

    如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;

    诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容


作者:海子 
出处:http://www.cnblogs.com/dolphin0520/


2.int、char、long各占多少字节数

int 4字节 char 2字节 long 8字节


3. int和Integer的区别

  • 1、Integer是int的包装类,int则是java的一种基本数据类型
  • 2、Integer变量必须实例化后才能使用,而int变量不需要
  • 3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
  • 4、Integer的默认值是null,int的默认值是0

延伸:
关于Integer和int的比较
1、由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。

1
2
3
Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false

2、Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)

1
2
3
Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true

3、非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)

1
2
3
Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false

4、对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
对于第4条的原因:
java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100);,而java API中对Integer类型的valueOf的定义如下:
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}

java对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了


4. Java多态的理解

一、 多态的概念:同一操作作用于不同对象,可以有不同的解释,有不同的执行结果,这就是多态,简单来说就是:父类的引用指向子类对象

二、 实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。

三、 多态的作用:消除类型之间的耦合关系。

四、 现实中,关于多态的例子不胜枚举。比方说按下 F1键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果

五、 多态存在的三个必要条件

  • 一、要有继承;
  • 二、要有重写;
  • 三、父类引用指向子类对象。

六、多态的好处:

  1. 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
  2. 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
  3. 接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
  4. 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
  5. 简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
  6. 当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,多态在继承链中对象方法的调用存在一个优先级:this.show(O)super.show(O)this.show((super)O)super.show((super)O)
    子类的对象,先在子类中查找是否有覆盖的方法,没有就去父类查找该方法,如果还没有,就在子类调用继承于父类的参数,并强转为父类的参数的方法,如果还没有,调用父类中方法,并将参数转为父类

5. Java中的String,StringBuilder,StringBuffer三者的区别

这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面。

  • 1、首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String
    String最慢的原因:
    String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。
  • 2、 再来说线程安全
    在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的
      如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

  • 3、总结一下
      String:适用于少量的字符串操作的情况
      StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
      StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况


6. 什么是内部类?内部类的作用

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:成员内部类、局部内部类、匿名内部类和静态内部类。下面就先来了解一下这四种内部类的用法。

  • 1.成员内部类
      成员内部类是最普通的内部类,它的定义为位于另一个类的内部,形如下面的形式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Circle {
    double radius = 0;
    public Circle(double radius) {
    this.radius = radius;
    }
    class Draw { //内部类
    public void drawSahpe() {
    System.out.println("drawshape");
    }
    }

    这样看起来,类Draw像是类Circle的一个成员,Circle称为外部类。成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。

    不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

    1
    2
    外部类.this.成员变量
    外部类.this.成员方法

    虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class Circle {
    private double radius = 0;
    public Circle(double radius) {
    this.radius = radius;
    getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问
    }
    private Draw getDrawInstance() {
    return new Draw();
    }
    class Draw { //内部类
    public void drawSahpe() {
    System.out.println(radius); //外部类的private成员
    }
    }
    }

    成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。创建成员内部类对象的一般方式如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public class Test {
    public static void main(String[] args) {
    //第一种方式:
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建
    //第二种方式:
    Outter.Inner inner1 = outter.getInnerInstance();
    }
    }
    class Outter {
    private Inner inner = null;
    public Outter() {
    }
    public Inner getInnerInstance() {
    if(inner == null)
    inner = new Inner();
    return inner;
    }
    class Inner {
    public Inner() {
    }
    }
    }

     内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。

  • 2.局部内部类
    局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class People{
    public People() {
    }
    }
    class Man{
    public Man(){
    }
    public People getWoman(){
    class Woman extends People{ //局部内部类
    int age =0;
    }
    return new Woman();
    }
    }

    注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

  • 3.匿名内部类
      匿名内部类应该是平时我们编写代码时用得最多的,在编写事件监听的代码时使用匿名内部类不但方便,而且使代码更加容易维护。下面这段代码是一段Android事件监听代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    scan_bt.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
    });
    history_bt.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
    });

    这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。这段代码中的:

    1
    2
    3
    4
    5
    6
    7
    8
    new OnClickListener() {
    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub
    }
    }

    匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

  • 4.静态内部类
      静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。


Java内部类详解 
https://www.cnblogs.com/dolphin0520/p/3811445.html

7. 抽象类和接口区别

抽象类和接口的对比
参数 抽象类 接口
默认的方法实现 它可以有默认的方法实现 接口完全是抽象的。它根本不存在方法的实现
实现 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现
构造器 抽象类可以有构造器 接口不能有构造器
与正常Java类的区别 除了你不能实例化抽象类之外,它和普通Java类没有任何区别 接口是完全不同的类型
访问修饰符 抽象方法可以有public、protected和default这些修饰符 接口方法默认修饰符是public。你不可以使用其它修饰符。
main方法 抽象方法可以有main方法并且我们可以运行它 接口没有main方法,因此我们不能运行它。
多继承 抽象方法可以继承一个类和实现多个接口 接口只可以继承一个或多个其它接口
速度 它比接口速度要快 接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
添加新方法 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 如果你往接口中添加方法,那么你必须改变实现该接口的类。
什么时候使用抽象类和接口
  • 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。
  • 如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。
  • 如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。

Java抽象类与接口的区别
http://www.importnew.com/12399.html

8. Java中为何要定义抽象类

抽象方法:由abstract修饰的方法为抽象方法,抽象方法只有方法的定义,没有方法的实现。
抽象类:一个类中如果包含抽象方法,个i类应该用abstract关键字声明为抽象类。
抽象类不可以实例化,即使一个类中没有抽象方法,也可以将其定义为抽象类,同样,该类不可以实例化。
抽象类的意义:

  • 1、为子类提供一个公共的类型;
  • 2、封装子类中重复内容(成员变量和方法);
  • 3、定义有抽象方法,子类虽然有不同的实现,但该方法的定义是一致的。

9. 抽象类和接口的使用场景

语义上的区别:
首先 类描述的是 这个东西是什么(强调所属)?包含了静态属性,静态行为 ,属性和行为。
而接口 描述的它能做什么事儿(强调行为)? 只是 静态常量属性 和 行为

abstract class的应用场合
一句话,在既需要统一的接口,又需要实例变量或缺省的方法的情况下,就可以使用它。最常见的有:

  • A. 定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口。可以用abstract class定义一组方法体,甚至可以是空方法体,然后由子类选择自己所感兴趣的方法来覆盖。
  • B. 某些场合下,只靠纯粹的接口不能满足类与类之间的协调,还必需类中表示状态的变量来区别不同的关系。abstract的中介作用可以很好地满足这一点。
  • C. 规范了一组相互协调的方法,其中一些方法是共同的,与状态无关的,可以共享的,无需子类分别实现;而另一些方法却需要各个子类根据自己特定的状态来实现特定的功能
    其他情况下都是使用 接口。

应该这样说,我们再开始使用的时候就是用的接口,后来实现的子类里有些子类有共同属性,或者相同的方法实现,所以提取出来一个抽象类,作为类和接口的中介。


抽象类和接口的使用场景
http://blog.csdn.net/xiaoliuliu2050/article/details/61931498

10. 泛型通配符extends与super的区别

<? extends T>限定参数类型的上界:参数类型必须是T或T的子类型
<? super T> 限定参数类型的下界:参数类型必须是T或T的超类型
总结为:

  • 1.<? extends T> 只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入
  • 2.<? super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收
  • 3.? 既不能用于入参也不能用于返参

11. 父类的静态方法能否被子类重写

静态方法是针对于类而言的,而重写和继承是针对于对象实例的,不能针对于静态方法,因为静态方法在程序启动已经分配内存,所有引用该方法的对象,都指向内存中同一地址,所以子类并不会重写,即使子类定义了相同名称的静态方法,也只是分配了一块内存给子类的静态方法,没有重写的说法。

12. 进程和线程的区别

  • 1.定义
    进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
    线程:进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
  • 2.关系
    一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
    相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

  • 3.区别
      进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
    1、简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
    2、线程的划分尺度小于进程,使得多线程程序的并发性高。
    3、另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
    4、线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
    5、从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

  • 4.优缺点
    线程和进程在使用上各有优缺点:
    线程执行开销小,但不利于资源的管理和保护;
    而进程正相反。
    同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。


https://www.cnblogs.com/lgk8023/p/6430592.html

13. final、finally、finalize区别

  • Final
    Final用于修饰类、成员变量和成员方法。final修饰的类,不能被继承(String、StringBuilder、StringBuffer、Math,不可变类),其中所有的方法都不能被重写,所以不能同时用abstract和final修饰类(abstract修饰的类是抽象类,抽象类是用于被子类继承的,和final起相反的作用);Final修饰的方法不能被重写,但是子类可以用父类中final修饰的方法;Final修饰的成员变量是不可变的,如果成员变量是基本数据类型,初始化之后成员变量的值不能被改变,如果成员变量是引用类型,那么它只能指向初始化时指向的那个对象,不能再指向别的对象,但是对象当中的内容是允许改变的

  • Finally
    Finally通常和try catch搭配使用,保证不管有没有发生异常,资源都能够被释放(释放连接、关闭IO流)。

  • Finalize
    Finalize是object类中的一个方法,子类可以重写finalize()方法实现对资源的回收。垃圾回收只负责回收内存,并不负责资源的回收,资源回收要由程序员完成,Java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法用于使对象释放资源(如关闭连接、关闭文件),之后才进行垃圾回收,这个方法一般不会显示的调用,在垃圾回收时垃圾回收器会主动调用。


http://blog.csdn.net/beixiaozhang/article/details/52955862

14. 序列化的方式

  • Android开发中的序列化有两种方法。
      第一种是实现Serializable接口(是JavaSE本身就支持的),第二种是实现Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。实现Serializable接口非常简单,声明一下就可以了,而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能
  • 两种方式的区别
    1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
    2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
    3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。

15.静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?

java中静态属性和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏.
原因:

  • 1.静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成对,不需要继承机制及可以调用。如果子类里面定义了静态方法和属性,那么这时候父类的静态方法或属性称之为”隐藏”。如果你想要调用父类的静态方法和属性,直接通过父类名.方法或变量名完成,至于是否继承一说,子类是有继承静态方法和属性,但是跟实例方法和属性不太一样,存在”隐藏”的这种情况。
  • 2.多态之所以能够实现依赖于继承、接口和重写、重载(继承和重写最为关键)。有了继承和重写就可以实现父类的引用指向不同子类的对象。重写的功能是:”重写”后子类的优先级要高于父类的优先级,但是“隐藏”是没有这个优先级之分的。
  • 3.静态属性、静态方法和非静态的属性都可以被继承和隐藏而不能被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象。非静态方法可以被继承和重写,因此可以实现多态

16. 静态内部类使用的目的

静态内部类可以看做和外部类平级的类,静态内部类不可以访问外部类的非静态变量与成员方法,而非静态内部类,可以访问外部类成员变量和方法,但是内部不允许出现静态成员和静态方法。

创建静态内部类实例不需要绑定在外部类的实例

17. String 转换成 Integer的方式及原理

  • String 转 Integer 的方式

    1
    i = Integer.valueOf(str);
  • String 转 Integer 原理
    先来看看 在Integer 类中 Valueof方法:

    1
    2
    3
    public static Integer valueOf(String s) throws NumberFormatException {
    return Integer.valueOf(parseInt(s, 10));
    }

    分析一下parseInt(s, 10)方法,这里只摘取其中关键代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    public static int parseInt(String s, int radix)
    throws NumberFormatException
    {
    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;
    if (len > 0) {
    char firstChar = s.charAt(0);
    if (firstChar < '0') { // Possible leading "+" or "-" //基本不用管
    if (firstChar == '-') {
    negative = true;
    limit = Integer.MIN_VALUE;
    } else if (firstChar != '+')
    throw NumberFormatException.forInputString(s);
    if (len == 1) // Cannot have lone "+" or "-"
    throw NumberFormatException.forInputString(s);
    i++; // i自增
    }
    multmin = limit / radix; // multmin = limit/10;
    while (i < len) {
    // Accumulating negatively avoids surprises near MAX_VALUE
    digit = Character.digit(s.charAt(i++),radix);
    if (digit < 0) {
    throw NumberFormatException.forInputString(s);
    }
    if (result < multmin) {
    throw NumberFormatException.forInputString(s);
    }
    result *= radix;
    if (result < limit + digit) {
    throw NumberFormatException.forInputString(s);
    }
    result -= digit;
    }
    } else {
    throw NumberFormatException.forInputString(s);
    }
    return negative ? result : -result;
    }
文章目录
  1. 1. 1. java中==和equals和hashCode的区别
  2. 2. 2.int、char、long各占多少字节数
  3. 3. 3. int和Integer的区别
  4. 4. 4. Java多态的理解
  5. 5. 5. Java中的String,StringBuilder,StringBuffer三者的区别
  6. 6. 6. 什么是内部类?内部类的作用
  7. 7. 7. 抽象类和接口区别
    1. 7.0.1. 抽象类和接口的对比
    2. 7.0.2. 什么时候使用抽象类和接口
  • 8. 8. Java中为何要定义抽象类
  • 9. 9. 抽象类和接口的使用场景
  • 10. 10. 泛型通配符extends与super的区别
  • 11. 11. 父类的静态方法能否被子类重写
  • 12. 12. 进程和线程的区别
  • 13. 13. final、finally、finalize区别
  • 14. 14. 序列化的方式
  • 15. 15.静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
  • 16. 16. 静态内部类使用的目的
  • 17. 17. String 转换成 Integer的方式及原理
  • |