当一个对象被当作参数传递到另一个方法时,此方法可以改变这个对象的属性,可以返回改变后的结果,这里是值传递还是引用传递?
值传递,java中方法调用只支持参数的值传递,对象的属性可以在被调用的过程中被改变,但是这个改变不会影响到被调用方
String和StringBuilder、StringBuffer的区别
- 都是催字符串的存储和操作,其中String是只能读取字符串,也就是说String修饰的字符串不能被改变。
- 而StringBuffer和StringBuilder指的是一个字符串对象可以直接进行修改;StringBuffer是线程安全的,StringBuilder不是线程安全的,所以StringBuilder效率比StringBuffer高,这两个类的方法完全相同,StringBuilder是java 5引用的
JVM如何加载.class文件的,加载.class文件的原理机制
- 类的加载是由类加载器(ClassLoader)及其子类完成,它主要负责在运行时查询和装入类文件中的类:
- 由于java的跨平台性,经过编译的java源程序不是一个可执行的程序,而是一个或多个类文件。类的加载是指把类的.class文件中的数据读取到内存中,会创建一个字节数组读入.class文件,然后会产生与加载类对应的class对象,加载完毕后,这个class对象还是不完整的,这个类还是不可用的;接 下来这个类会进入一个连接阶段,这个阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)、解析(将符号引用替换成直接引用)三个步骤;最后JVM对类进行初始化,包括:如果类存在直接的父类并且这个父类没有被初始化,那么就首先初始化父类;如果类中存在初始化语句,就会一次执行这些初始化语句。
- 这些过程哦都是通过类加载器完成的,包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)、自定义加载器(java.lang.ClassLoader的子类)。从jdk1.2以后,类加载得过程采用了父类委托机制(PDM),指的是在这个机制中,JVM自带的Bootstrap是根加载器,其他的加载器有且仅有一个父类加载器。类的加载首先请求父类加载器,父类加载器无能为力时候才由其子类加载器加载,
- Bootstrap:负责加载JVM的核心类库
- Extension:从系统指定的目录加载类库,父加载器是Bootstrap
- System:应用加载器,父类是Extension,它会从环境变量classpath或者系统属性所指定的目录中加载类,是用户自定义加载器的默认父级加载器
抽象类和接口的区别:
- 都不能进行实例化
- 抽象类使用abstract;接口使用interface
- 一个类可以实现多个接口,但是只能继承一个抽象类
- 抽象类中可以是private、默认、public、protected;接口只能是public
- 有抽象方法的类必须声明为抽象类,没有抽象方法的类可以声明为抽象类
- 抽象类中可以定义成员变量,接口中定义的成员变量实际上是常量
内部类和静态内部类区别
- 静态内部类使用static修饰,不需要依赖外部类实现实例化;
- 普通内部类需要通过外部类来实例化
抽象方法是否是可以是静态的,是否可以是本地方法,是否可以被synchronized修饰
- 都不能,静态方法不能被重写,而抽象方法需要子类继承;
- 本地代码是指由本地代码实现的方法,而抽象方法没有实现;
- synchronized修饰的是业务逻辑,而抽象方法没有逻辑
静态变量和实例变量区别
- 静态变量使用static修饰,不属于类,一个静态变量在内存中只有一个,存放在方法区中;
- 实例变量属于类,需要先创建类对象然后才能使用实例变量
对象克隆方法
- 实现Cloneable接口重写clone()
- 实现Serializable接口,通过对象序列化和反序列化实现
一个.java源文件是否可以包含多个类
- 可以,但是一个源文件中最多只能有一个public类,而且文件名必须与 public类名一致
内部类可以引用外部类的成员,包括私有方法
final关键字
- 修饰类:类不能被继承
- 修饰方法:方法不能被重写
- 修饰变量:赋值之后不能被修改
TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?
- TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。
- TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。
- Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象必须实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。
sleep()和yield()
- sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会
- 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态
- leep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常
多线程实现方式
- 继承Thread类,通过重写run()方法来定义线程的行为(java 5之前)
- 实现Runnable接口,通过重写run()方法来定义线程的行为(java 5之前)
- 实现Callable接口,重写call()
synchronized的用法
- 可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问
- 可以用synchronized(对象) { … }定义同步代码块
- 声明方法时将synchronized作为方法的修饰符
同步和异步举例说明
- 同步:正在读取一条数据时,另一个线程正在对其进行写操作;一个线程对数据进行写操作,另一个线程正在进行读取这个数据,这些就应该实现同步,阻塞式操作
- 异步:当程序访问一个方法需要浪费大量时间的时候,并且不希望程序等待方法等待返回时,可以使用异步,非阻塞式操作
synchronized 和java.util.concurrent.locks.Lock
- Lock:能够完成sychronization所有功能,java 5新增的API;不强制要求一定要获取锁;需要手动释放锁,最好在finally中释放
- synchronization:会自动释放锁;
获得一个类的类对象的方式
- 类型.class:String.class
- 对象.getClass():“a”.getClass()
- Class.forName():Class.forName(“java.lang.String”)
通过反射创建对象的方法:
- 类对象调用newInstance():“a”.getClass().newInstance()
- 通过类对象获取构造器,然后调用newInstance():String.class.getConstructor(String.class).newInstance(“a”)
通过反射调用对象的方法
- Method m = “a”.getClass().getMethod(“toUpperCase”);
- m.invoke(“a”)//输出A
如何解决高并发问题
并发就是可以使用多个线程或进程,同时处理(就是并发)不同的操作。
解决方式:
- 使用缓存
- 使用生成静态页面
- 图片服务器分离:降低服务器系统压力,可保证系统不会因为图片问题而崩溃
- 写代码时尽量减少不必要的资源浪费
- 不要频繁使用new对象,对于整个应用中只需要存在一个实例的类使用单例模式,使用stringBuffer或stringBuilder代替string
- 使用synchronized
进程和线程
- 进程是系统进行资源分配和调度的一个独立单元
- 线程是进程的一个实体,是CPU分配时间片的基本单位,是比进程更小的能独立运行的基本单位
- 关系:一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以是并发的
线程同步的方法
- 使用sychronized同步方法
- 使用sychronized同步代码块
- 使用特殊域变量volatile
- 使用重入锁ReentrantLock:lock() :获得锁;unlock() :释放锁
sleep()与wait()区别:
-
sleep()方法正在执行的线程主动让出CPU(然后CPU就可以去执行其他任务),在sleep指定时间后CPU再回到该线程继续往下执行
(注意:sleep方法只让出了CPU,而并不会释放同步资源锁!!!);
-
wait()方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用wait()的线程才会解除wait状态,可以去参与竞争同步资源锁,进而得到执行。
(注意:notify的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说notify只是让之前调用wait的线程有权利重新参与线程的调度);
-
使用位置:sleep()方法可以在任何地方使用;wait()方法则只能在同步方法或同步块中使用;
-
所属不同:sleep()是线程线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait()是Object的方法,调用会放弃对象锁,进入等待队列,待调用notify()/notifyAll()唤醒指定的线程或者所有线程,才会进入锁池,不再次获得对象锁才会进入运行状态
error和exception区别
- Error类和Exception类都是继承Throwable类
- Error是系统中的错误,程序员是不能改变的和处理的。一般是指与虚拟机相关的问题,如系统崩溃,虚拟机错误,内存空间不足,方法调用栈溢等。
- Exception表示程序可以处理的异常,可以捕获且可能恢复
运行时异常:RuntimeException及其子类,当程序抛出一个异常时,不会检查改代码片段是否有对异常的处理
编译时异常:RuntimeException以外的异常,要求必须有处理手段否则编译不通过
例子:error和Exception像是水池和水池里的水
水池崩溃等于外部环境有关是error;水污染了,影响水质的因素是Exception
9.throw和throws区别
Throw是在方法体中,抛出一个具体的异常
Throws用来声明一个方法可能产生的异常,不做任何处理而是将异常向上抛,谁调用就抛给谁
常见的运行时异常
- NullPointerException:空指针异常
- ClassCastException:类型转化异常
- IndexOutOfBoundsException:下标越界异常
- IllegalArgumentException:非法参数异常
- ArithmeticException:算数异常
- ArrayIndexOutOfBoundsException:数组下标越界异常
- StringIndexOutOfBoundsException:字符串下标越界
- NumberFormatException:数字格式化异常
Servlet生命周期
- 加载:类加载
- 实例化
- 初始化:init()
- 处理:service(),doGet(),doPost()
- 销毁:destry()
Servlet执行流程
实例化对象的方法
- new对象
- 利用反射:Class.forName(“java.long.String”).newInstance();
- 通过工厂方法返回:Integer.valueOf(1);
- 调用对象的clone()方法:实现Cloneable接口并重写clone()方法
- 实现Serializable接口,通过对象的序列化和反序列化
java打日志的方式
-
System.out.println();
-
java.util.Logging提供的:
Logger log = Logger.getLogger("personLog");
-
Log4j:
Logger log = LoggerFactory.getLogger(PersonLog.class);
-
commen-loggin:
Log log = LogFactory.getLog(PersonLog.class);
-
@Slf4j
直接使用log.info()就行了
Object类
类 | 说明 |
---|---|
hashCode() | 返回该对象的哈希码值 |
equals(Object obj) | 是否相等 |
Class<?> getClass() | 返回运行时的类 |
Object clone() | 返回此对象的副本 |
String toString() | 返回对象的字符串表示 |
void notify() | 唤醒一个正在等待此对象的线程 |
void notifyAll() | 唤醒所有正在等待此对象的线程 |
void wait() | 使此对象的线程进入等待状态 |
void wait(long timeout) | 超过指定时间后使此对象的线程进入等待状态 |
wait(long timeout, int nanos) | 允许更好地控制的时间等待一个通知放弃之前的量 |
void finalize() | 当垃圾回收器要回收一个对象之前调用,让对象处理他随后的事 |
集群、分布式、微服务区别
- 集群是同一个业务,部署在多个服务器上
- 分布式是一个业务拆分成多个子业务,每个子业务分别部署在不同的服务器上
- 微服务也是将不同的功能模块拆分成多个服务,和分布式的区别在于,微服务的每个服务不一定部署在不同的服务器上,可以部署在同一个服务器上
RPC、HTTP、TCP
-
RPC远程过程调用,是一个计算机通信协议,可以像调用方法一样调用服务器的服务;支持同步和异步;
- 协议:客户端和服务端之间建立TCP连接,可以一次建一个,也可以多个调用符用一个链接;
- 数据包小;
- 采用二进制进行传输,传输效率高,
- 使用自身负载均衡
-
HTTP:超文本传输协议,是一种应用层协议,规定了网络传输的请求格式、响应格式、资源定位和操作的方式等
- HTTP协议,
- 数据包大,
- 采用的是json格式进行数据传输;
- 需配置nginx进行负载均衡
-
TCP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据
TCP/IP共分为四个层次:网络接口层、网络层、传输层和应用层
在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议
在传输层中有TCP协议与UDP协议
在应用层有HTTP、FTP、TELNET、SMTP、DNS等协议
具体参考:TCP/IP协议 -
rpc调用过程及说明:
RPC调用过程
说明:
- 调用者(client functions)已本地调用的方式发起调用,到达client stub
- client stub收到调用后会将请求的参数:接口名,方法名,参数类型,参数值等进行封装打包成特定格式的能进行网络传输的消息体
- client stub会将消息体通过网络发送给服务端sockets
- 然后服务端(server stub)按照相应的格式对接收到的数据进行拆包,获取到方法名参数等
- server functions得到数据根据方法名和参数进行本地调用,并将结果再次打包传输的到server stub,并通过网络发送给客户端client stub
- client stub接收到消息之后,进行拆包处理返回给client functions
- client functions 得到结果,rpc结束
HTTP流程:
HTTP请求方式
- OPTIONS:主要用于客户端测试服务器的功能
- HEAD:与GET类似,获取响应头中的消息
- GET:向指定的资源发送请求并返回实体,消息放在请求头中,不安全并且数据量少,主要用于查询操作
- POST:向制定资源提交数据,数据放在请求体中,相对于GET安全,可请求大量数据,一般用于新增、删除、编辑
- PUT:向指定资源是上传数据(上传图片、文件[待确认])
- DELETE:请求服务器删除指定的资源
- TRACE:回显服务器收到的请求,主要用于测试和诊断
- CONNECT:HTTP/1.1中预留给能够能够将连接改为管道方式的代理服务器
es和influxdb
es:
- 是一个基于lucence的实时搜索服务器,本身是一个应用
- 支持restful格式http接口来操作和展示界面
influxdb:
- 开源分布式时序数据库。使用 Go 语言编写,无需外部依赖。其设计目标是实现分布式和水平伸缩扩展
- 提供类似sql的查询语言
区别
- ES支持全文检索
- 两者都可以使用grafana做为展示
- 对于数字的一些监控,可使用influxdb。而对于日志,文本存储可以使用ES