GitHub:https://github.com/JDawnF
声明:题目大部分来源于Java后端公众号,有些个人整理,但答案皆为个人整理,仅供参考。
目录
Exception、Error、运行时异常与一般异常有何异同
String、StringBuilder、StringBuffer
什么是Java序列化和反序列化,如何实现Java序列化?或者请解释Serializable 接口的作用
Object类中常见的方法,为什么wait notify会放在Object里边?
-
Java中有几种基本数据类型,各占几个字节?
-
面向对象的特征:继承、封装和多态
- 继承:多个类具有共同的属性(成员变量)与行为(成员方法)的时候,将这些共同的部分抽取出来定义到一个公共的类中,其他及各类可以与这个公共的类形成继承关系,从而在多个类中不需要重 复定义公共部分!这个公共的类就是父类,也称为超类或者基类,其他的类就是子类。子类可以直接访问父类的非私有化成员变量,访问父类的私有化成员变量可以使用super.get()方法。
- 封装:所谓封装指的是隐藏对象的属性以及实现细节,仅对外提供访问方式,将不需要对外提供的内容进行隐藏,把属性隐藏对外提供访问方式。使用private修饰。
- 多态: java程序中定义的引用变量所指向的具体类型和通过该引用类型发出的方法在调用时不确定,该引用变量发出的方法到底调用哪个类的实现的方法,必须在程序运行期间才能决定。
- 多态的成员特点:成员变量:编译与运行时期都看父类!
成员方法:编译时期看父类,运行时期看子类
- 多态的成员特点:成员变量:编译与运行时期都看父类!
-
final, finally, finalize 的区别
- final:Java的关键字之一,被final修饰的类不能被继承,所以要注意一个类不能被abstract和final同时修饰;被final修饰的变量不能被修改,所以一开始要先赋值。当final修饰的成员变量为引用数据类型时,在赋值后其指向地址无法改变,但是对象内容还是可以改变的。
- finally:捕获异常中的finally模块,不管有没有异常被抛出、捕获,finally块都会被执行。
-
finally什么时候会被执行:
- 在try...catch...finally语句中,只要try语句之前程序没有抛异常,或者在try语句中程序没有退出(System.exit(0))的话,就会执行;
- 加入try语句中有return语句,那么会先执行finally语句中的内容,因为如果执行了return语句程序就会结束退出;
- 此外,要注意方法内部的变量都是存放在栈里面,函数执行结束后,其对应的栈会被回收,那么方法体中定义的变量也就不存在了,所以return语句实际上是拷贝了一份值,然后再返回的。所以在finally中如果有return语句的话,对基本类型的值不影响,但是对引用类型的值就会有影响。
-
- finalize:这是Object类中的一个方法,在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。 一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,它与析构函数不同。
-
Exception、Error、运行时异常与一般异常有何异同
- Exception:分为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于RuntimeException;而程序本身没有没有问题,但由于像I/O错误这类异常导致的异常属于其他异常。
IOException(其他异常)
FileNotFoundException(文件未找到异常。)
IOException(操作输入流和输出流时可能出现的异常。)
EOFException (文件已结束异常) - Error:描述了java运行时系统的内部错误和资源耗尽错误。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。应用程序不应该抛出这种类型的对象。
- 运行时异常:对于运行时异常,java编译器不要求必须进行异常捕获处理或者抛出声明,由程序员自行决定。
-
Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显示地进行捕获处理,这是编译期检查的一部分。Error,是 Throwable 不是 Exception。不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。
-
粉色的异常是需要被抛出的。
- Exception:分为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于RuntimeException;而程序本身没有没有问题,但由于像I/O错误这类异常导致的异常属于其他异常。
-
请写出5种常见到的runtime exception
- IndexOutOfBoundsException(下标越界异常)
- NullPointerException(空指针异常)
- NumberFormatException (String转换为指定的数字类型异常)
- ArithmeticException -(算术运算异常 如除数为0)
- ArrayStoreException - (向数组中存放与声明类型不兼容对象异常)
- SecurityException -(安全异常)
-
int 和 Integer 有什么区别,Integer的值缓存范围
- Integer是int的包装类;int是基本数据类型;
- Integer变量必须实例化后才能使用;int变量不需要;
- Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
- Integer的默认值是null;int的默认值是0。
- 由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。
- Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
- 非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
- 对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
- 深入描述
-
public class Test { public static void main(String[] args) { //在-128~127 之外的数 Integer num1 = 128; Integer num2 = 128; System.out.println(num1==num2); //false // 在-128~127 之内的数 Integer num3 = 9; Integer num4 = 9; System.out.println(num3==num4); //true } }
解析原因:归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)。
加大对简单数字的重利用,Java定义在自动装箱时对于值从–128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象。
而如果超过了从–128到127之间的值,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。 -
https://blog.csdn.net/why15732625998/article/details/79437930#commentBox
-
- 源码分析:
- 给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,源码如下:
-
public static Integer valueOf(String s, int radix) throws NumberFormatException { return Integer.valueOf(parseInt(s,radix)); } 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); }
- IntegerCache是Integer的内部类,源码如下:
/** * 缓存支持自动装箱的对象标识语义 * -128和127(含)。 * * 缓存在第一次使用时初始化。 缓存的大小 * 可以由-XX:AutoBoxCacheMax = <size>选项控制。 * 在VM初始化期间,java.lang.Integer.IntegerCache.high属性 * 可以设置并保存在私有系统属性中 */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }
-
包装类,装箱和拆箱
- 包装类:每一个基本的数据类型都会一一对应一个包装类型,如:boolean--Boolean,int--Integer;
- 装箱:把基本的数据类型转换成对应的包装类型;
- Integer.valueOf(1)
- Integer i=1; 自动装箱,实际上在编译时会调用Integer.valueOf方法来装箱
- 这里留意一下IntegerCache,这是Integer常量池,Integer默认范围在-128~127之间,也就是在这个范围的数我们不用new一个Integer对象,直接Integer i=1定义即可,会实现自动装箱,所以这也说明无论创建多少个在这个范围的数,它们的valueOf()都是“==”,这里的high值是可以调动的。此外,在Long和Short中也有同样的缓存机制
-
拆箱:就是把包装类型转换为基本数据类型,基本数据类型 名称=对应的包装类型。
-
Integer i=1;
-
int j=i; //自动拆箱 int j=i=intValue(); 手动拆箱
-
自动拆箱:实际上会在编译时调用intValue()。
-
-
基本类型和对应的包装类可以相互装换:
- 由基本类型向对应的包装类转换称为装箱,例如把 int 包装成 Integer 类的对象;
- 包装类向对应的基本类型转换称为拆箱,例如把 Integer 类的对象重新简化为 int。
-
String、StringBuilder、StringBuffer
- 在这方面运行速度快慢为:StringBuilder > StringBuffer > String。效率比较String<StringBuffer<StringBuilder,操作的数据量小的时候可以用String。
StringBuffer的append方法,他是线程安全的
- String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。如下图,String为不可变
-
String str="abc"; System.out.println(str); str=str+"de"; System.out.println(str);
如果运行这段代码会发现先输出“abc”,然后又输出“abcde”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。另外,有时候我们会这样对字符串进行赋值。
-
String str="abc"+"de"; StringBuilder stringBuilder=new StringBuilder().append("abc").append("de"); System.out.println(str); System.out.println(stringBuilder.toString());
这样输出结果也是“abcde”和“abcde”,但是String的速度却比StringBuilder的反应速度要快很多,这是因为第1行中的操作和String str="abcde";是完全一样的,所以会很快,而如果写成下面这种形式:
-
String str1="abc"; String str2="de"; String str=str1+str2;
那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。
- 线程安全:StringBuilder是线程不安全的,而StringBuffer是线程安全的
- 如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。
-
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
-
为了实现修改字符序列的目的,StringBuffer 和 SringBuilder 底层都是利用可修改的(char,JDK 9 以后是 byte)数组,二者都继承了 AbstractStringBuilder,里面包含了基本操作,区别仅在于是否加锁。
- 在这方面运行速度快慢为:StringBuilder > StringBuffer > String。效率比较String<StringBuffer<StringBuilder,操作的数据量小的时候可以用String。
-
重载和重写的区别
https://blog.csdn.net/Andya_net/article/details/76815259
- 重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型,是一个类中多态性的一种表现。重载的规则:
-
必须具有不同的参数列表;
-
可以有不同的返回类型,只要参数列表不同就可以了;
-
可以有不同的访问修饰符;可以抛出不同的异常;
-
- 重写要求返回值、方法名和参数都相同,子类抛出的异常不能超过父类相应方法抛出的异常。(子类异常不能超出父类异常);子类方法的的访问级别不能低于父类相应方法的访问级别(子类访问级别不能低于父类访问级别)。重写的规则:
- 参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。
- 返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。
- 访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
- 重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:
- 父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。
- 重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型,是一个类中多态性的一种表现。重载的规则:
-
抽象类和接口有什么区别
- 抽象类由abstract关键字修饰,不能被private修饰,因为抽象类不能实例化,需要被继承,所以抽象类也不能被final修饰;
- 接口中定义了一些动作(即方法),接口中的方法默认为public abstract,可以含有变量,但是接口中的变量默认为public abstract final。
接口修饰符只能用public、default和abstract。 不能用final、static修饰。在jdk1.8之后,可以用static修饰方法了。
-
相同点:都不能被实例化;接口的实现类或者抽象类的子类都只有实现了接口或抽象类中的方法才能被实例化
-
不同点:
- 接口只能定义方法,抽象类中可以定义和实现接口需要实现,
- 抽象类需要继承,一个类可以实现多个接口但只能继承一个类
- 接口中成员变量是public static final,只能有静态的不能被修改的数据,必须赋值,所有的方法都是public abstract,而且只能被这两个修饰。抽象类可以有自己的成员变量,抽象类中的成员变量默认default、private、protected和public。可以再子类中重新定义、赋值。抽象类中的方法不能用private、static、synchronized、native修饰符。
-
说说反射的用途及实现
-
泛型与类型擦除
https://www.jianshu.com/p/4de08deb6ba4
- 泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口和泛型方法。
- Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经被替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码。
- 源程序:
public static void main(String[] args){ List <Integer> listInt=new ArrayList <Integer>(); List <String> listString=new ArrayList <String>(); Map<String, String> map = new HashMap<String, String>(); map.put("AAA", "BBB"); map.put("CCC", "DDD"); System.out.print(map.get("AAA")); }
-
编译后:
public static void main(String[] paramArrayOfString) { ArrayList localArrayList1 = new ArrayList(); ArrayList localArrayList2 = new ArrayList(); HashMap localHashMap = new HashMap(); localHashMap.put("AAA", "BBB"); localHashMap.put("CCC", "DDD"); System.out.print((String)localHashMap.get("AAA")); }
因此对于运行期的Java语言来说,
ArrayList <Integer>与ArrayList<String>
编译出来的代码是一样的,所以说泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型。 -
类型擦除:在jdk1.5之后,Java引进了泛型的概念,在不确定具体的类型,或者说想使用多种类型的时候,可以用泛型来表示,但是代码在具体执行的时候需要指定具体的类型,因此会在代码编译阶段,泛型会被具体的类型替换,这也就是类型擦除。举个简单的例子,Map<String,T> 这个map在写代码的时候可以不指定具体的类型,但是具体在执行的时候,需要确定类型的,如果不确定具体的类型,是没有办法确定value是哪一种类型的,而这个确定类型的动作就是在编译的时候确定的,也就是类型擦除。
-
说说自定义注解的场景及实现
-
HTTP请求的GET与POST方式的区别
参照:https://blog.csdn.net/striveb/article/details/84635456 -
HTTP请求总共有哪几种类型
- 除了get和post,还有一下这几种:
- HEAD:与GET请求类似,不同在与服务器只返回HTTP头部信息,没有页面内容
- PUT:上传指定URL的描述
- DELETE:删除指定资源
- OPTIONS:返回服务器支持的HTTP方法
- CONNECT:转换为透明TCP/IP隧道的连接请求
-
常见的状态码
https://blog.csdn.net/striveb/article/details/84070336 -
Session与Cookie区别
- 前言:HTTP是一种无状态的协议,为了分辨链接是谁发起的,需自己去解决这个问题。不然有些情况下即使是同一个网站每打开一个页面也都要登录一下。而Session和Cookie就是为解决这个问题而提出来的两个机制。
- session原理(有时间限制,默认30分钟,浏览器关闭即消失):
- 浏览器第一次访问服务器时会创建一个session对象并返回一个JSESSIONID=ID的值,创建一个Cookie对象key为JSSIONID,value为ID的值,将这个Cookie写回浏览器;
- 浏览器在第二次访问服务器的时候携带Cookie信息JSESSIONID(Java中)=ID的值,如果该JSESSIONID的session已经销毁,那么会重新创建一个新的session再返回一个新的JSESSIONID通过Cookie返回到浏览器;
- 针对一个web项目,一个浏览器是共享一个session,就算有两个web项目部署在同一个服务器上,针对两个项目的session是不同的。 如:你在tomcat上同时部署了两个web项目,分别是web1、web2。当你在一个浏览器上同时访问web1时创建的session是A1,访问web2时创建的session是A2。后面你再多次访问web1使用的session还是A1,多次访问web2时使用session就是A2
-
session是基于Cookie技术实现,重启浏览器后再次访问原有的连接依然会创建一个新的session,因为Cookie在关闭浏览器后就会消失,但是原来服务器的Session还在,只有等到了销毁的时间会自动销毁;
-
如果浏览器端禁用了Cookie,那么每次访问都会创建一个新的Session,但是我们可以通过服务器端程序重写URL即可,如果页面多连接多,会增加不必要的工作量,那可以强制让你用户开启接收Cookie后再让其访问即可。无法禁用服务器的session
-
两者区别:
- Cookie和Session都是会话技术,Cookie是保存在客户端,Session是保存在服务器端。
- Cookie有大小限制以及浏览器在存cookie的个数也有限制,Session是没有大小限制和服务器的内存大小有关。
- Cookie有安全隐患(因为存在客户端),通过拦截或本地文件找得到你的cookie后可以进行攻击。
- Session是保存在服务器端上会存在一段时间才会消失,如果session过多会增加服务器的压力。
- 存储数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String 类型的对象。
- Session过多时会消耗服务器资源,大型网站会有专门Session服务器,Cookie存在客户端没问题。
- 域的支持范围不一样,比方说a.com的Cookie在a.com下都能用,而www.a.com的Session在api.a.com下都不能用,解决这个问题的办法是JSONP或者跨域资源共享。
-
列出自己常用的JDK包
-
MVC设计思想
- 概念:MVC是一种设计思想,主要分为三层:1)模型层: 主要是业务逻辑,包含了业务数据的加工与处理以及相应的基础服务(为了保证业务逻辑能够正常进行的事务、安全、权限、日志等等的功能模块)
2)视图层:展现模型处理的结果,即对数据进行了渲染展示;另外,还要提供相应的操作界面,方便用户使用。3)控制层:接受客户端发过来的请求,由控制器来选择相应的模型来处理;模型返回的结果给控制器,由控制器选择合适的视图。
-
在Java中,对于MVC的应用主要是:
web层:Servlet(Controller)和JSP(View);service层(业务逻辑层,Model): service和JavaBean;数据访问层:dao
- 概念:MVC是一种设计思想,主要分为三层:1)模型层: 主要是业务逻辑,包含了业务数据的加工与处理以及相应的基础服务(为了保证业务逻辑能够正常进行的事务、安全、权限、日志等等的功能模块)
-
equals与==的区别
- equals是object类中的方法,从Object类中的源码中可以看出,其实equals主要也是调用了“==”;如果我们程序中没有重写equals方法的话,默认就是调用了Object类中的equals方法
其他类可以重写equals方法,比如下面这个是Integer类对equals这个方法的重写,先判断类型,再判断是否相等public boolean equals(Object obj) { return (this == obj); }
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
-
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
-
1、比较的是操作符两端的操作数是否是同一个对象。
2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。
-
-
equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。
-
简单说:equals比较的只是值是否相等,而“==”比较的是地址是否相等,此外,要注意String类型的比较,如果常量池中已存在某个字符串的话,那么此时“==”的比较结果为true。
-
"=="比"equals"运行速度快,因为"=="只是比较引用。
- equals是object类中的方法,从Object类中的源码中可以看出,其实equals主要也是调用了“==”;如果我们程序中没有重写equals方法的话,默认就是调用了Object类中的equals方法
-
hashCode和equals方法的区别与联系
- hashCode方法是通过哈希算法计算一个对象实例的哈希值(即地址);equals方法判断一个对象实例所指向的值或者两个值是否相等;
- hashCode效率会比较高,但是并不是完全可靠,因为生成hash值的算法可能有问题,所以可能会导致两个对象生成的hash值是一样的;
- 两个obj,如果equals()相等,hashCode()一定相等。
两个obj,如果hashCode()相等,equals()不一定相等(Hash散列值有冲突的情况,虽然概率很低)。 - https://www.cnblogs.com/jesonjason/p/5492208.html
- https://www.cnblogs.com/keyi/p/7119825.html
-
什么是Java序列化和反序列化,如何实现Java序列化?或者请解释Serializable 接口的作用
- 序列化与反序列化:将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象。序列化就是一种用来处理对象流的机制,就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间,可以将其保存在硬盘上,进行持久化。
- 序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的。
- 在IDEA中可以用这个插件生成SerializableID,下载后可以设置快捷键。SerializableID作为唯一标识一个类,如果这个类被修改,增加了某些属性,SerializableID会发生变化,SerializableID用于判断类和对象是否是同一个版本。
-
Object类中常见的方法,为什么wait notify会放在Object里边?
- wait,notify,notifyAll 是定义在Object类的实例方法,用于控制线程状态。
- wait(),notify(),notifyAll()都必须使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步 才具有锁。
- 这些方法之所以在Object里头主要是因为:1、这些方法存在于同步中; 2、使用这些方法必须标识同步所属的锁;
3、锁可以是任意对象,所以任意对象调用方法一定定义在Object类中。4、因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调用wait()和notify();所以wait和notify属于Object。等待和唤醒必须是同一个锁。 - notify() :唤醒在此对象监视器上等待的单个线程。
- wait() :导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
- wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
- https://blog.csdn.net/m0_37531231/article/details/79574665
-
Java的平台无关性如何体现出来的
- 所谓的平台无关就是指软件的运行不会因操作系统、处理器的变化而无法运行或出现运行错误。Java通过jvm来实现平台无关性。
- Java提供了jre,JRE由Java虚拟机,类库和一些核心文件组成,也就是说,只要平台提供了Java运行环境,Java编写的软件就可以在其上运行。
-
Java语言的运行原理:
在一个计算机上编译得到的字节码文件(就是.class文件),可以复制到任何一个安装了Java运行环境的计算机上直接运行。然后字节码文件由虚拟机负责解释执行,即Java虚拟机将字节码翻译成本地计算机的机器码,然后将机器码交给本地的操作系统运行。由于在一个计算机上编译得到的字节码文件可以复制到任何一个安装了Java运行环境的计算机上直接使用,所以字节码其实是一种“中间代码”,这也就是为什么“Java语言能够一次编译,处处运行,也就是Java跨平台的原因。”所以称Java是一种“半编译,半解释的语言”,即源程序——>编译——>字节码——>字节码解释程序——>对应平台的机器语言。”
-
JDK和JRE的区别
- JDK(Java Development Kit)是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。
- Java Runtime Environment(JRE)是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。JVM是Java Virtual Machine(Java虚拟机)的缩写,是整个java实现跨平台的最核心的部分,能够运行以Java语言写作的软件程序。
-
Java 8有哪些新特性
-
成员变量与局部变量的区别有那些
- 从语法形式上,看成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰;
- 从变量在内存中的存储方式来看,成员变量是对象的一部分,而对象存在于堆内存,局部变量存在于栈内存
- 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
- 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被 final 修饰但没有被 static 修饰的成员变量必须显示地赋值);而局部变量则不会自动赋值。
参照:https://blog.csdn.net/why15732625998/article/details/79437930#commentBox