一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?
这个是可以的,一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致。
每个编译单元只能有一个public 类。这么做的意思是,每个编译单元只能有一个公开的接口,而这个接口就由其public 类来表示。
你可以根据需要,往这个文件里面添加任意多个提供辅助功能的package 权限的类。
但是如果这个编译单元里面有两个或两个以上的public 类的话,程序就不知道从哪里导入了,编译器就会报错。
java语言中有没有goto关键字?
goto是java语言中的保留字,目前还没有在java中使用。
但是,但是你想过没有,为什么面试官要问你这个问题?他是要考察你的知识面是否广泛!!!
那么当你遇到这个题目时,你应该这样答:
其实goto这个词是C语言中的,goto语句通常与条件语句配合使用,可用来实现条件转移,
构成循环,跳出循环体等功能。而在结构化程序语言中一般不主张使用goto语句, 以免造成程序流程的混乱,
使理解和调试程序都产生困难。
但是在java语言中,goto这个词只是作为了保留字,还没有使用。那是因为java语言讲究简单,方便。
说说&和&&的区别。
共同点:&和&&都可以用作逻辑与(and)运算,当运算符两边都为true时结果才为true,否则为false.
不同点:&&运算符有短路的功能,即当运算符左边的值为true时,右边则不会进行运算,直接跳过.
&运算符没有短路功能.但是是可以用作位运算.
在JAVA中如何跳出当前的多重嵌套循环?
break;
问题:Java中,char型变量中能不能存储一个中文汉字,为什么?
* char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,
* 所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在
* unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充
* 说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
* 备注:后面一部分回答虽然不是在正面回答题目,但是,为了展现自己的学识和表现自己
* 对问题理解的透彻深入,可以
* 回答一些相关的知识,做到知无不言,言无不尽。
用最有效率的方法算出2乘以8等於几?
最有效的方法是:
public class Demo02 {
public static void main(String args[]){
int a=2<<3;
System.out.println(a);
}
}
解析:
a << b就表示把a转为二进制后左移b位(在后面添b个0)。
例如100的二进制为1100100,而110010000转成十进制是400,那么100 << 2 = 400。
可以看出,a << b的值实际上就是a乘以2的b次方,因为在二进制数后添一个0就相当于该数乘以2。
通常认为a << 1比a * 2更快,因为前者是更底层一些的操作。
因此程序中乘以2的操作请尽量用左移一位来代替。 定义一些常量可能会用到<<运算。
你可以方便地用1 << 16 - 1来表示65535。很多算法和数据结构要求数据规模必须是2的幂,
此时可以用<<来定义Max_N等常量。 和<<相似,a >> b表示二进制右移b位(去掉末b位),
相当于a除以2的b次方(取整)。我们也经常用>> 1来代替div 2,比如二分查找、堆的插入操作等等。
想办法用>>代替除法运算可以使程序效率大大提高。最大公约数的二进制算法用除以2操作来代替慢得出奇的mod运算,
效率可以提高60%。
Java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?超详细解析
/*
* 问题:使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变
* 答:
* 使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
*/
public class Test10 {
// final修饰基本类型的变量
public static final char CHAR = '中';
// final修饰引用类型的变量
public static final StringBuffer a = new StringBuffer("StringBuffer");
public static void main(String[] args) {
// 编译报错,引用不能变
// a = new StringBuffer("hehe");
// 引用变量所指向的对象中的内容还是可以改变的
a.append("xxx");
}
public static int method1(final int i) {
// i = i + 1;// 编译报错,因为final修饰的是基本类型的变量
return i;
}
// 有人在定义方法的参数(引用变量)时,可能想采用如下的形式来阻止方法内部修改传进来的参数对象,
// 实际上,这是办不到的,在该方法内部任然可以增加如下代码来修改参数对象
public static void method2(final StringBuffer buffer) {
buffer.append("buffer");// 编译通过,因为final修饰的是引用类型的变量
}
}
静态变量和实例变量的区别(配图解释专业术语,通俗易懂)
1:首先在语法定义上区别:静态变量前面要加static,实例变量不用
2:在程序运行时:实例变量输入对象的属性,必须创建了实例对象(如 new)才会被分配空间,
才可以使用实例变量,静态变量不属于某个实例对象,而是属于类,也叫类变量,只要程序加载了类的字节码,
不用创建任何实例对象就会被分配空间,就可以被使用
3:总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
注意:(static)静态变量的使用也是有局限性的,一个静态方法中不能调用类中的非静态的方法和变量,static修饰的变量在类加载后在内存中只有一份内存空间,可以被一个类的所有实例对象所共享,如:总库100张票,4个窗口卖火车票,卖的都是总库里的票,
无论是哪个窗口卖掉的票,总票都会减一。
是否可以从一个static方法内部发出对非static方法的调用?
不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,
才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以
直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例
对象,如果从一个static方法中发出对非static方法的调用,那个非static
方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部
发出对非static方法的调用。
Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相对应,
例如,ceil的英文意义是天花板,该方法就表示向上取整,
所以,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;
floor的英文意义是地板,该方法就表示向下取整,
所以,Math.floor(11.6)的结果为11,Math.floor(-11.6)的结果是-12;
最难掌握的是round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),
即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
Overload和Override的区别?Overloaded的方法是否可以改变返回值的类型?
接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?抽象类中是否可以有静态的main方法?
Java中abstract class和interface的区别
arrayList和vector的区别
try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
会执行,在return前执行
运行时异常与一般异常有何异同?
Java中堆和栈的区别在什么地方?
堆
(1)Java的堆是一个运行时数据区,类的对象从堆中分配空间。这些对象通过new等指令建立,通过垃圾回收器来销毁。
(2)堆的优势是可以动态地分配内存空间,需要多少内存空间不必事先告诉编译器,因为它是在运行时动态分配的。但缺点是,由于需要在运行时动态分配内存,所以存取速度较慢。
例如:String name = new String("33")中的 new String("33")
栈
(1)栈中主要存放一些基本数据类型的变量(byte,short,int,long,float,double,boolean,char)和对象的引用。
(2)栈的优势是,存取速度比堆快,栈数据可以共享。但缺点是,存放在栈中的数据占用多少内存空间需要在编译时确定下来,缺乏灵活性。
例如:String name 中的name
我们能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?
可以的。JVM中专门有一条指令叫i2b,就是从整型转成字节型,超出的部分会被直接截掉。
a.hashCode() 有什么用?与 a.equals(b) 有什么关系?
//hashCode方法部分源码
public native int hashCode();
//equals方法部分源码
public boolean equals(Object obj) {
return (this == obj);
}
a.hashCode() 有什么用?
hashCode()方法提供了对象的hashCode值,是一个native方法,返回的默认值与System.identityHashCode(obj)一致。
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。
equals与hashCode的关系?
equals()相等的两个对象,hashCode()一定相等;
hashCode()不相等,一定能推出equals()也不相等;
hashCode()相等,equals()可能相等,也可能不等。
java中字节流与字符流的区别
以stream结尾都是字节流,reader和writer结尾都是字符流。
InputStream是所有字节输入流的父类,OutputStream是所有字节输出流的父类。
Reader是字符输入流的父类,Writer是字符输出流的父类。
字节流:
文件流:FileOutputStream和FileInputStream
缓冲流:BufferedOutputStream和BufferedInputStream
对象流:ObjectOutputStream和ObjectInputStream
字符流:
转换流:InputStreamReader和OutputStreamWriter
缓冲字符流:PrintWriter和BufferedReader
区别:
读写的时候一个是按字节读写,一个是按字符。
在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。
只是读写文件,和文件内容无关的,一般选择字节流。
什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用
我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,
例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,
这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传输,
但是,jre本身就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,
如果要让java 帮我们做,要被传输的对象必须实现serializable接口,
这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,
这就是所谓的序列化。需要被序列化的类必须实现Serializable接口,该接口是一个mini接口,
其中没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的。
例如,在web开发中,如果对象被保存在了Session中,tomcat在重启时要把Session对象序列化到硬盘,
这个对象就必须实现Serializable接口。如果对象要经过分布式系统进行网络传输或通过rmi等远程调用,
这就需要在网络上传输对象,被传输的对象就必须实现Serializable接口。
Java提高篇——JVM加载class文件的原理机制
JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后会写个复杂点class ,然后再找一些开源框架,比如Spring ,Hibernate 等等,再然后就开发企业级的应用,比如网站、企业内部应用、实时交易系统等等,直到某一天突然发现做的系统咋就这么慢呢,而且时不时还来个内存溢出什么的,今天是交易系统报了StackOverflowError ,明天是网站系统报了个OutOfMemoryError ,这种错误又很难重现,只有分析Javacore 和dump 文件,运气好点还能分析出个结果,运行遭的点,就直接去庙里烧香吧!每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子了。我想Java 做的久一点的都有这样的经历,那这些问题的最终根结是在哪呢?—— JVM 。
JVM 全称是Java Virtual Machine ,Java 虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使用 VMWare不一样,那个虚拟的东西你是可以看到的,这个JVM 你是看不到的,它存在内存中。我们知道计算机的基本构成是:运算器、控制器、存储器、输入和输出设备,那这个JVM 也是有这成套的元素,运算器是当然是交给硬件CPU 还处理了,只是为了适应“一次编译,随处运行”的情况,需要做一个翻译动作,于是就用了JVM 自己的命令集,这与汇编的命令集有点类似,每一种汇编命令集针对一个系列的CPU ,比如8086 系列的汇编也是可以用在8088 上的,但是就不能跑在8051 上,而JVM 的命令集则是可以到处运行的,因为JVM 做了翻译,根据不同的CPU ,翻译成不同的机器语言。
JVM 中我们最需要深入理解的就是它的存储部分,存储?硬盘?NO ,NO , JVM 是一个内存中的虚拟机,那它的存储就是内存了,我们写的所有类、常量、变量、方法都在内存中,这决定着我们程序运行的是否健壮、是否高效,接下来的部分就是重点介绍之。
类加载器的作用是加载类文件到内存,比如编写一个HelloWord.java 程序,然后通过javac 编译成class 文件,那怎么才能加载到内存中被执行呢?Class Loader 承担的就是这个责任,那不可能随便建立一个.class 文件就能被加载的,Class Loader 加载的class 文件是有格式要求,在《JVM Specification 》中式这样定义Class 文件的结构:
https://www.cnblogs.com/Qian123/p/5707562.html
java异常中throw和throws的区别
https://blog.csdn.net/weixin_38011265/article/details/79149313
说一说Servlet的生命周期
servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。
这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。
Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,
service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,
当服务器决定将实例销毁的时候调用其destroy方法。
web容器加载servlet,生命周期开始。通过调用servlet的init()方法进行servlet的初始化。
通过调用service()方法实现,根据请求的不同调用不同的do*()方法。
结束服务,web容器调用servlet的destroy()方法。
Servlet API中forward()与redirect()的区别?
转发:forward()是使用RequestDispatcher接口中的forward()方法来实现,
需要request 和 response作为参数,就是将用户的请求,连同请求信息等内容,一起转发到服务器的另外一个servlet去处理,它不会丢失request信息。这一过程是服务器内部完成的,作为访问者,是感觉不到了,或者说是透明的,因此访客浏览器的url 是不会发生变化的。
重定向:重定向redirect()是通过HttpServletResponse对象的sendRedirect()来实现,该方法相当于浏览器重新发送一个请求 response.sendRedirect(path); 会丢失request的所有信息, 它属于页面级的重定向,仅仅让你的浏览器重新访问一个新的url,作为浏览者,能很明显的看到浏览器url地址的变化,这和点击了一个普通的超链接的后果是一样的。
两者的选择:
forward()方法更加高效, 在forward()方法可以满足需要时, 尽量使用 forward()方法, 并且,
这样也有助于隐藏实际的链接。 在有些情况下, 比如, 需要跳转到一个其它服务器上的资源, 则必须使用
request.getParameter() 和request.getAttribute() 区别
当你要传递普通的数据类型给下一个页面时,你在下一个页面中就可以用getParameter()方法来获得上一个页面传递过来的数据了!(普通的数据类型是指int,float,double,string等在Java中常用的基本类型,但是在下一个页面中你用getParameter()方法获得的值永远只能时String类型的,你可以把String类型转换为你所需要的类型!)
当你要传递一个对象给下一个页面时,你就要使用getAttribut()方法了!
如:你要把一个List或Map传递到下一个页面,这时你就必须要用setAttribut()和getAttribut()方法传递数据了!
从更深层次的考虑,getParameter()方法传递数据,只会从WEB客户端传递到WEB服务器,
代表HTTP请求数据,getParameter()方法返回String类型的数据!
setAttribut()和getAttribut()方法传递的数据只会在WEB服务器内部,在具有转发关系的WEB组件之间传递,
这两个方法能设置Object类型的共享数据!
JDBC的脏读是什么?哪种数据库隔离级别能防止脏读?
什么是幻读,哪种隔离级别可以防止幻读?
MyBatis中使用#和$书写占位符有什么区别?
#将传入的数据都当成一个字符串,会对传入的数据自动加上引号;$将传入的数据直接显示生成在SQL中。
注意:使用$占位符可能会导致SQL注射攻击,
能用#的地方就不要使用$,写order by子句的时候应该用$而不是#
面试题—Mybatis动态sql是什么意思?常用的标签有哪些和用途?
choose:choose(when,otherwise)标签相当于switch(case,default),如title为空时,
when标签里的代码,则不执行。默认会执行otherwise表签里的代码。
HashMap的存储原理
数组使用下标维护数据,所以查找起来比较快,但是插入和删除的话需要移动后面的数据,数据插入和删除比较慢。
链表使用指针来维护链表结构,查找起来比较慢,因为要从第一个结点开始查找,但是插入和删除的话不需要移动数据,
只需要改变指针的指向就可以了,所以插入和删除比较快。
HashMap提供高效的查找,插入和删除。是怎么做到的?
HashMap的存储结构
HashMap底层是以数组方式进行存储的。将key-value键值对作为数组的一个元素进行存储。
Key-value都是Map.Entry中的属性。其中将key的值进行hash之后进行存储,即每一个key都是计算hash值,然后再存储。
每一个hash值对应一个数组下标,数组下标是根据hash值和数组长度计算得来的。
由于不同的key值可能具有相同的hash值,即一个数组的某个位置出现两个相同的元素,
对于这种情况,hashmap采用链表的形式进行存储。
List:是存储单列数据的集合,存储的数据是有序并且是可以重复的
Map:存储双列数据的集合,通过键值对存储数据,存储 的数据是无序的,Key值不能重复,value值可以重复 key和value是一一对应的
Set接口
Set接口直接继承自Collection接口,并且方法接口上也一模一样。Set对添加的元素有一些要求,其不允许出现重复的元素,并且元素之间没有次序。这相当于一个不允许重复的离散的集合。因此,添加进Set的元素类型需要定义equals方法。若是使用自定义的类,则应该重写equals方法来确保实现自己需要的功能。
Set接口主要实现了两个类:HashSet,TreeSet。
HashSet是按照哈希来存取元素的,因此速度较快。HashSet继承自抽象类AbstractSet,然后实现了Set、Cloneable、Serializable接口。
TreeSet也是继承自AbstractSet,不过不同的是其实现的是NavigableSet接口。而NavigableSet继承自SortedSet。SortedSet是一个有序的集合。其添加的元素必须实现了Comparable接口,因为其在添加一个元素的时候需要进行排序。NavigableSet则提供了更多的有关元素次序的方法
List接口
List接口也是继承自Collection。与Set不同的是,List可以存储重复的元素。主要有两种实现:ArrayList和LinkedList。
ArrayList没有什么好说的,就像传统的数组一样,有着很快的随机存取速度,但是插入删除的速度就很慢。
LinkedList则与ArrayList恰恰相反,因为用链表来保存数据,所以插入删除元素的速度很快,但是访问数据的速度就不如ArrayList了。
Map接口
Map(映射)是一个存储键值对的容器接口。每一个元素包含一个key对象和value对象,且元素不允许重复。
Map接口的实现有以下几个:
HashMap是最常用的一个实现。HashMap使用hash映射来存取数据,这个速度是相当快,是O(1)的速度。其容量capacity,和负载因子load factor可以在一开始设定。当元素个数达到capacity*load factor的时候,就会进行扩容。
LinkedHashMap和HashMap类似,只不过内部用链表来维护次序。因此遍历时候的顺序是其插入顺序。
TreeMap是基于红黑树的Map,插入的数据被有次序保存,并且有很高的效率。因此在遍历输出的时候可以得到排序的数据。但是这要求插入的数据实现了comparable接口。
总结
Collection、Set、List和Map都是接口,不能被实例化。
Set和List都继承自Collection,而Map则和Collection没什么关系。
Set和List的区别在于Set不能重复,而List可以重复。
Map和Set与List的区别在于,Map是存取键值对,而另外两个则是保存一个元素。
1、Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现
2、HashMap允许将null作为一个entry的key或者value,而Hashtable不允许
3、HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。
4、最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap
就必须为之提供外同步。
一个.java类中是可以有多个类。但是,在多个类中,有且只有一个public类,且public类的类名必须与*.java的文件名相一致。JVM虚拟机实例通过调用某个类的main()来执行程序,这个main()必须时public static void 并接受一个字符串作为参数,但是该类不一定是public类。
char型变量中能不能存贮一个中文汉字?为什么?
是能够定义成为一个中文的,因为java中以unicode编码,一个char占16个字节,所以放一个中文是没问题的
使用 final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
使用 final 关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
例如,对于如下语句:
final StringBuffer a=new StringBuffer("immutable");
执行如下语句将报告编译期错误:
a=new StringBuffer("");
但是,执行如下语句则可以通过编译:
a.append("broken!")
静态变量和实例变量的区别;
1:首先在语法定义上区别:静态变量前面要加static,实例变量不用
2:在程序运行时:
实例变量输入对象的属性,必须创建了实例对象(如 new)才会被分配空间,才可以使用实例变量,静态变量不属于某个实例对象,而是属于类,也叫类变量,只要程序加载了类的字节码,不用创建任何实例对象就会被分配空间,就可以被使用
3:总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
64 位 JVM 中,int 的长度是多数?
Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32 位 和 64 位 的Java 虚拟机中,int 类型的长度是相同的。