1.谈谈你对Java面向对象的理解?

面向对象就是把构成问题的事务分解成一个个对象,建立对象的目的不是一个步骤,而是为了描述一个事务在解决问题中的行为。类是面向对象的一个重要概念,类是很多个具有相同属性和行为特征的对象抽象出来的,对象是类的一个实例。

类具有三个属性:继承、封装和多态。

封装:通过把程序模块化、对象化,通过把这些具体事物的特性属性和通过这些属性实现的具体方法放到一个类中。核心思想就是“隐藏细节”,“数据安全”。利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能的隐藏内部的细节,只保留一些对外的接口使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流交互。

继承:子类可以继承父类的属性和方法,当需要新的属性和方法时,可以对其进行拓展。

多态:子类在继承父类的方法和属性的同时,当需要实现同一事务,表现出不同的行为特征,此时需要面向对象的另一特性,多态。需要在子类中把父类中实现某一事物的行为特征重新实现一遍,多态包含了重写和重载。重写就是把子类从父类那里继承的方法重新写一遍,这样父类里相同的方法就被覆盖了,还可以通过super. 方法调用父类的方法;重载是类中方法名相同,参数不同的情况,可以使形参类型不同,形参个数不同或者形参顺序不同,但是返回值类型必须相同。还可以通过继承的上下转型,接口的回调来实现。

2.Java面向对象的特征?

封装、继承和多态。

3.谈谈你对String、StringBuffer、StringBuilder的理解?

3.1String类使用“+”进行字符串拼接操作

(1)字符串常量+字符串常量

编译器直接将两个常量优化为一个字符串常量

(2)字符串变量+字符串常量,解析一下步骤:

a.StringBuilder s=new StringBuilder();

b.s.append("母");

c.s.append("亲");

d.String str=S.toString();

3.2String

(1). String是不可变的,它每次的字符串拼接都是new一个新的String进行接收。final修饰了底层的字符数组,因此内容不可变。jdk8是char[]数组,jdk9中改成了byte[]数组和一个标示编码的coder(utf16)(因为char[]占两个字节,byte占1个字节)

 

(2).String类的运行创建机理

由于String在Java世界中使用过于频繁,Java为了避免在一个系统中使用大量的Java对象,引入了字符串常量池的概念。

其运行机制是:创建一个字符串的时候,首先检查池中是否有相等的字符串对象,如果有就不需要创建,直接从池中找到对象引用。如果没有的话,新建字符串对象,返回对象引用。但是通过new方法创建的不会检查常量池中是否存在,而是在堆或栈中重新创建一个对象,也不会把对象放在常量池中,上面的情况只适用于直接给String引用赋值的情况。

注意:jdk6中String是immutable Strng提供了inter()方法可以将Strng对象添加到池中,并且返回该对象的引用。(如果由equals()确定池中有该字符串,那就直接返回)。

在 Java6 中,在 String 类中提供了 intern() 方法(不推荐使用)。它实现的功能:如果缓存里有字符串,就返回缓存里的实例,如果没有,就把它加到缓存里。

被缓存的字符串存在于 PermGen(永久代)里,这里空间很小,并且基本只有 FullGC 这样的垃圾收集器来光顾。所以很容易 OOM 错误。所以在后来,就被放到了 堆 中。设置永久代在Java 8中被元数据区替代了。

当两个String对象拥有相等的值的时候,他们只引用字符串中同一个拷贝。当同一个字符串大量出现的时候,可以大量节省内存空间。

3.3StringBuilder和StringBuffer

StringBuilder和StringBuffer底层都是利用了可修改的数组,都集成了AbstractStringBuilder,里面包含了基本操作。区别在于StringBuffer添加了synchronized.。

3.4String和StringBuilder、StringBuffer的比较

3.4.1运行速度

StringBuilder>StringBuffer>String

StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对对象进行更改,而不进行创建和回收的操作,String类针对字符串拼接过程,变量+字符串常量。底层操作参考字符串的拼接过程,所以String最慢。

3.4.2线程安全

StringBuilder是线程不安全的,而StringBuffer是线程安全的,StringBuffer带有Synchronized关键字,所以可以保证线程是安全的。StringBuilder的方法没有该关键字,所以不能保证线程安全,有可能会出现不安全的操作。

总之:

String:适用于少量的字符串操作的情况。

StringBuffer:适用于多线程下在字符缓冲区进行大量操作的情况。

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况。

4.谈谈你对Synchronized关键字的理解?

Synchronized关键字解决的是多个线程之间访问资源的同步性。

4.1 Synchronized的三种使用方法:

(1)修饰实例方法,作用于当前对象实例加锁,进入同步代码块前需要获取当前对象实例的锁。

(2)修饰静态方法,作用于当前类对象的锁,进入同步代码块前需要获取当前类对象的锁。也就是给当前类加锁,会作用于当前类的所有对象实例,因为静态成员不属于任何一个实例对象,是类成员(static表示这是该类的一个静态资源,不管new了多少个对象,都只有一份,所以对该类的所有对象都加了锁),所以如果线程A调用了一个实例对象的非静态Synchronized方法,而线程B调用了该实例对象所属类的静态Synchronized方法,不会发生互斥,因为访问静态Synchronized方法,占用的是当前类的锁,而访问非静态Synchronized占用的是当前实例对象的锁。

(3)修饰代码块,指定加锁对象,在进入同步代码块前需要获取给定对象的锁。

Synchronized是同步锁:

(1)修饰一个代码块,被修饰的代码块称为同步语句块,作用的范围是整个代码块内部,作用的对象是调用整个代码块的对象。

(2)修饰一个方法,被修饰的方法是同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象。

(3)修饰一个静态方法,其作用的范围是整个静态方法,作用的对象是整个类的所有对象。

(4)修饰一个类,其作用的范围是整个类内部,作用的对象是整个类的所有对象。

4.2Synchronized的原理

实现原理:JVM是通过进入、退出对象监视器(Monitor)来实现对方法、同步块同步的,而对象监视器(Monitor)的实现依赖于底层操作系统的互斥锁(Mutex Lock)实现。具体实现是在编译之后再同步方法调用前加入一个monitor.enter指令。在退出方法和异常前插入monitor.exit指令。对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程monitor.exit之后才能尝试继续获取锁。当执行monitor.enter指令时,线程试图获取monitor的持有权,当计数器为0时可以成功获取,相应的锁计数器置为1即加1,当执行monitor.exit时,锁计数器置为0,表明锁被释放,当线程获取对象锁失败时,线程就要进入阻塞等待,直到其他线程释放锁为止。

对Synchronized修饰方法时,添加一个ACC.SYNCHRONIZED来标识,该标识指明了该方法是一个同步方法。JVM通过该标示来判断一个方法是否是同步方法,从而执行相应的同步调用。

4.3Synchronized的优化

Synchronized是一种重量级锁,会涉及到操作系统状态的切换。影响效率。jdk1.6中进行了优化,为了减少获取和释放锁带来的消耗引入了偏向锁和轻量锁。(后面介绍)

5.谈谈你对单例模式的理解?

Java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例,饿汉式单例、登记式单例三种。

5.1.单例模式有一下特点:

(1)单例类只能有一个实例。

(2)单例类只能自己创建自己的唯一实例。

(3)单例类必须给所有其他对象提供这一实例。

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志、对象、对话框、打印机、显卡的驱动程序常被设计成单例模式。singleton通过将构造方法限定为private避免了类在外部被实例化。在同一虚拟机范围内,singleton的唯一实例只能通过getlnstance()方法访问。(事实上,通过java反射机制是能够实例化构造方法为private的类的,但是基本会使所有的Java单例模式失效,姑且认为反射机制不存在)

5.2.时间和空间

比较以上两种方法,懒汉模式是典型的时间换空间,每次在获取实例前,都会进行判断看是否需要进行创建实例,浪费时间,但是如果如果一直不使用的话,则不会创建实例,将诶月内存空间。

饿汉模式是典型的空间换时间,在类装载的时候方法调用之前就已经创建出来,不管你用不用,先创建出来,每次调用的时候就不需要再判断了,节省了时间。

5.3.线程安全

(1)不加Synchronized的懒汉模式是不安全的,例如线程A在创建实例时,首先判断是否需要创建实例,判断为true,创建实例,在还为创建完成时,线程B也进入了创建实例,判断结果也为true,此时也进入了创建实例中,此时创建出了两个实例,则单例模式失效。

(2)饿汉模式是线程安全的,因为虚拟机只会装载一次,在装载类的时候是不会发生并发的。

5.4.单例模式的优点

Java单例模式的作用是保证在java应用程序中,一个class只有一个实例存在,节省了内存空间,因为它限制了实例个数,有利于Java垃圾回收。

5.5.单例模式的应用

饿汉模式加载类的时候比较慢,但是运行时获取对象的速度比较快,从加载到应用结束会一直占用资源。

懒汉模式运行时获取对象的速度比较慢,但是加载类的速度比较快,它的整个应用的的生命周期只有一部分在占用资源。

这两种模式对于初始化较快,占用资源较少的轻量级对象没有较大差异。

对于初始化较慢,占用资源较多的重量级对象从用户角度分析选择饿汉模式比较好。因为虽然初始化的速度叫较慢,但是运行速度较快。

数据连接池应用单例模式是比较好的选择,可以屏蔽不同数据库之间的差异,降低系统对数据库的耦合性,可以对多个系统使用,提高复用性,提高数据库连接的管理。数据连接池是重量级对象,一个应用只需保存一份就好,节省资源,方便管理。

6.谈谈你对final关键字的理解

1.修饰变量

凡是对成员变量或者局部变量(在方法)声明final的变量都是final变量,final变量通常和static关键字一起使用,做为常量。

final修饰基本数据类型时,基本数据类型必须赋初值且不能改变,修饰引用变量时,该引用变量不能再指向其他对象。

 

2.修饰方法

final也可以修饰方法,方法前面final关键字,代表这个方法不可以被子类的方法重写。如果一个方法的功能已经足够完整。子类不需要改变的话,可以声明该方法是final。final方法比非final要快,因为在编译的时候已经静态绑定了。不需要在运行的时候动态绑定了。

 

3.修饰类

final修饰的类叫做final类,final类的功能通常是完整的,他们不能被继承,Java中有许多类是final,例如String、Integer以及其它包装类。

 

.4.深入理解java关键字

public final class Day4Test {
int i=5;
public int adds(int i){
return i;
}
public static void main(String[] args) {
System.out.println(new Day4Test().adds(6));
}
}
运行结果:
6

  

(2)static修饰变量时,在类加载时,该变量就已经被初始化,不会对象创建再次被加载,当变量被static修饰时就表示该变量只能被初始化一次。

public  class Day4Test {
public final double s = Math.random();
public static double j = Math.random(); public static void main(String[] args) {
Day4Test data1 = new Day4Test();
Day4Test data2 = new Day4Test();
System.out.println(data1.s);
System.out.println(data2.s);
System.out.println(data1.j);
System.out.println(data2.j);
}
}
运行结果:
0.5351276053333238
0.8784147384393909
0.8476665776623683
0.8476665776623683

  

static修饰的变量j被创建了两次,但是只初始化了一次,只没有被改变。

去年去阿里面试,面试官居然问我Java类和对象,我是这样回答的!的更多相关文章

  1. 去年去阿里面试,被问到java 多线程,我是这样手撕面试官的

    1.多线程的基本概念 1.1进程与线程 程序:是为完成特定任务,用某种语言编写的一组指令的集合,即一段静态代码,静态对象. 进程:是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程,每个程 ...

  2. 去年去阿里面试,被问到ArrayList和LinkedList,我是这样回答的!

    前言 在一开始基础面的时候,很多面试官可能会问List集合一些基础知识,比如: ArrayList默认大小是多少,是如何扩容的? ArrayList和LinkedList的底层数据结构是什么? Arr ...

  3. 那些面试官必问的JAVA多线程和并发面试题及回答

    Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环 ...

  4. 我说精通字符串,面试官竟然问我 Java 中的 String 有没有长度限制?

    String 是 Java 中很重要的一个数据类型,除了基本数据类型以外,String 是被使用的最广泛的了,但是,关于 String,其实还是有很多东西容易被忽略的. 就如本文我们要讨论的问题:Ja ...

  5. 我说我精通字符串,面试官竟然问我Java中的String有没有长度限制!?|附视频讲解

    关于String有没有长度限制的问题,我之前单独写过一篇文章分析过,最近我又抽空回顾了一下这个问题,发现又有了一些新的认识.于是准备重新整理下这个内容. 这次在之前那篇文章的基础上除了增加了一些验证过 ...

  6. 【性能优化】面试官:Java中的对象都是在堆上分配的吗?

    写在前面 从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:"Jav ...

  7. 求你了,再问你Java内存模型的时候别再给我讲堆栈方法区了…

    GitHub 4.1k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 4.1k Star 的 ...

  8. 阿里二面,面试官居然把 TCP 三次握手问的这么细致

    TCP 的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度.看似是简单的面试问题,如果你的回答不符合面试官期待的水准,有可能就直接凉凉了. 本文 ...

  9. 我以为我对Mysql索引很了解,直到我遇到了阿里的面试官

    GitHub 4.8k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 4.8k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 4.8k Star 的 ...

随机推荐

  1. app 自动化测试 - 多设备并发 -appium+pytest+ 多线程

    1.appium+python 实现单设备的 app 自动化测试 启动 appium server,占用端口 4723 电脑与一个设备连接,通过 adb devices 获取已连接的设备 在 pyth ...

  2. laravel 验证码 auth方式登录 中间件判断session是否存在

    首先下载laravel的插件 composer下载  实现验证码       composer require mews/captcha 在config/app.php进行配置 'providers' ...

  3. ERP收付款的操作与设计--开源软件诞生22

    赤龙ERP收款付款讲解--第22篇 用日志记录"开源软件"的诞生 [进入地址 点亮星星]----祈盼着一个鼓励 博主开源地址: 码云:https://gitee.com/redra ...

  4. python数学math和random模块

    math模块 关注公众号"轻松学编程"了解更多. 在使用math模块时要先导入 # 导入模块 import math 1.math.ceil(num) 对num进行向上取整 num ...

  5. (模板)graham扫描法、andrew算法求凸包

    凸包算法讲解:Click Here 题目链接:https://vjudge.net/problem/POJ-1113 题意:简化下题意即求凸包的周长+2×PI×r. 思路:用graham求凸包,模板是 ...

  6. P1526 [NOI2003]智破连环阵

    目录 题意描述 算法分析 闲话 初步分析 具体思路 剪枝一 剪枝二 剪枝三 总结一下 代码实现 预处理 剪枝一 剪枝二 剪枝三 二分图匹配 代码综合 结语 又是被楼教主虐的体无完肤的一天 题意描述 在 ...

  7. SAM学习笔记&AC自动机复习

    形势所迫,一个对字符串深恶痛绝的鸽子又来更新了. SAM 后缀自动机就是一个对于字符串所有后缀所建立起的自动机.一些优良的性质可以使其完成很多字符串的问题. 其核心主要在于每个节点的状态和$endpo ...

  8. 18 socket

    18 socket 推荐: http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml Socket=Ip address+ TC ...

  9. stm32与地磁传感器HMC5883L

    1.简介 霍尼韦尔 HMC5883L 是一种表面贴装的高集成模块,并带有数字接口的弱磁传感器芯片,应用于低成本罗盘和磁场检测领域.HMC5883L 包括最先进的高分辨率 HMC118X 系列磁阻传感器 ...

  10. java实现一个简单的单链表反转

    自定义一个单链表,实现链表反转: 1.普通方法实现 2.递归方式实现 package listNode; public class ReverseNode { public static void m ...