核心内容摘要
探索哔哩下载姬:B站视频资源管理的全方位解决方案
一个.java源文件中是否可以包括多个类不是内部类有什么限制可以有多个类但只能有一个public的类并且public的类名必须与文件名相一致。
Java有没有goto?java中的保留字现在没有在java中使用。
说说和的区别。
和都可以用作逻辑与的运算符表示逻辑与and当运算符两边的表达式的结果都为true时整个运算结果才为true否则只要有一方为false则结果为false。
还具有短路的功能即如果第一个表达式为false则不再计算第二个表达式例如对于if(str! null !str.equals(s))表达式当str为null时后面的表达式不会执行所以不会出现NullPointerException如果将改为则会抛出NullPointerException异常。
If(x33 y
y会增长If(x33 y
不会增长还可以用作位运算符当操作符两边的表达式不是boolean类型时表示按位与操作我们通常使用0x0f来与一个整数进行运算来获取该整数的最低4个bit位例如0x31 0x0f的结果为0x01。
在JAVA中如何跳出当前的多重嵌套循环在Java中要想跳出多重循环可以在外面的循环语句前定义一个标号然后在里层循环体的代码中使用带有标号的break语句即可跳出外层循环。
例如for(int i0;i10;i){for(intj0;j10;j){System.out.println(“i” i “,j” j);if(j
break ok;}}另外我个人通常并不使用标号这种方式而是让外层的循环条件表达式的结果可以受到里层循环体代码的控制例如要在二维数组中查找到某个数字。
int arr[][] ;boolean found false;for(int i0;iarr.length!found;i) {for(intj0;jarr[i].length;j){System.out.println(“i” i “,j” j);if(arr[i][j]
{found true;break;}}}
switch语句能否作用在byte上能否作用在long上能否作用在String上?在switche中e只能是一个整数表达式或者枚举常量更大字体整数表达式可以是int基本类型或Integer包装类型由于byte,short,char都可以隐含转换为int所以这些类型以及这些类型的包装类型也是可以的。
显然long和String类型都不符合switch的语法规定并且不能被隐式转换成int类型所以它们不能作用于swtich语句中。
switch语句能否作用在String上说错了Java
7之后已经支持这种写法了
short s1 1; s1 s11是int类型而等号左边的是short类型所以需要强转1 1;有什么错? short s1 1; s1 1;有什么错?(没有错)对于short s1 1; s1 s1 1;由于s11运算时会自动提升表达式的类型所以结果是int型再赋值给short类型s1时编译器将报告需要强制转换类型的错误。
对于short s1 1; s1 1;由于 是java语言规定的运算符java编译器会对它进行特殊处理因此可以正确编译。
char型变量中能不能存贮一个中文汉字?为什么?char型变量是用来存储Unicode编码的字符的unicode编码字符集中包含了汉字所以char型变量中当然可以存储汉字啦。
不过如果某个特殊的汉字没有被包含在unicode编码字符集中那么这个char型变量中就不能存储这个特殊汉字。
补充说明unicode编码占用两个字节所以char类型的变量也是占用两个字节。
用最有效率的方法算出2乘以8等於几?2 3(左移三位)因为将一个数左移n位就相当于乘以了2的n次方那么一个数乘以8只要将其左移3位即可而位运算cpu直接支持的效率最高所以2乘以8等於几的最效率的方法是2 3。
使用final关键字修饰一个变量时是引用不能变还是引用的对象不能变使用final关键字修饰一个变量时是指引用变量不能变引用变量所指向的对象中的内容还是可以改变的。
例如对于如下语句finalStringBuffer anew StringBuffer(immutable);执行如下语句将报告编译期错误anew StringBuffer();但是执行如下语句则可以通过编译a.append( broken!);有人在定义方法的参数时可能想采用如下形式来阻止方法内部修改传进来的参数对象public void method(final StringBuffer param){}实际上这是办不到的在该方法内部仍然可以增加如下代码来修改参数对象param.append(a);10静态变量和实例变量的区别在语法定义上的区别静态变量前要加static关键字而实例变量前则不加。
在程序运行时的区别实例变量属于某个对象的属性必须创建了实例对象其中的实例变量才会被分配空间才能使用这个实例变量。
静态变量不属于某个实例对象而是属于类所以也称为类变量只要程序加载了类的字节码不用创建任何实例对象静态变量就会被分配空间静态变量就可以被使用了。
总之实例变量必须创建对象后才可以通过这个对象来使用静态变量则可以直接使用类名来引用。
例如对于下面的程序无论创建多少个实例对象永远都只分配了一个staticVar变量并且每创建一个实例对象这个staticVar就会加1但是每创建一个实例对象就会分配一个instanceVar即可能分配多个instanceVar并且每个instanceVar的值都只自加了1次。
public class VariantTest{publicstatic int staticVar 0;publicint instanceVar 0;publicVariantTest(){staticVar;instanceVar;System.out.println(staticVar instanceVar);}}
是否可以从一个static方法内部发出对非static方法的调用不可以。
因为非static方法是要与对象关联在一起的必须创建一个对象后才可以在该对象上进行方法调用而static方法调用时不需要创建对象可以直接调用。
也就是说当一个static方法被调用时可能还没有创建任何实例对象如果从一个static方法中发出对非static方法的调用那个非static方法是关联到哪个对象上的呢这个逻辑无法成立所以一个static方法内部发出对非static方法的调用。
Integer与int的区别int是java提供的8种原始数据类型之一。
Java为每个原始类型提供了封装类Integer是java为int提供的封装类。
int的默认值为0而Integer的默认值为null即Integer可以区分出未赋值和值为0的区别int则无法表达出未赋值的情况。
例如要想表达出没有参加考试和考试成绩为0的区别则只能使用Integer。
在JSP开发中Integer的默认为null所以用el表达式在文本框中显示时值为空白字符串而int默认的默认值为0所以用el表达式在文本框中显示时结果为0所以int不适合作为web层的表单数据的类型。
在Hibernate中如果将OID定义为Integer类型那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的如果将OID定义为了int类型还需要在hbm映射文件中设置其unsaved-value属性为0。
另外Integer提供了多个与整数相关的操作方法例如将一个字符串转换成整数Integer中还定义了表示整数的最大值和最小值的常量。
Math.round(
11.
等於多少?Math.round(-
11.
等於多少?Math类中提供了三个与取整有关的方法ceil、floor、round这些方法的作用与它们的英文名称的含义相对应。
例如ceil的英文意义是天花板该方法就表示向上取整Math.ceil(
11.
的结果为12,Math.ceil(-
11.
的结果是-11floor的英文意义是地板该方法就表示向下取整Math.ceil(
11.
的结果为11,Math.ceil(-
11.
的结果是-12最难掌握的是round方法它表示“四舍五入”算法为Math.floor(x
0.
即将原来的数字加上
5后再向下取整所以Math.round(
11.
的结果为12Math.round(-
11.
的结果为-11。
这里有一些笔误floor的英文意义是地板该方法就表示向下取整Math.floor(
11.
的结果为11,Math.floor(-
11.
的结果是-
Overload和Override的区别Overloaded的方法是否可以改变返回值的类型?Overload是重载的意思Override是覆盖的意思也就是重写。
重载Overload表示同一个类中可以有多个名称相同的方法但这些方法的参数列表各不相同即参数个数或类型不同。
重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同通过子类创建的实例对象调用这个方法时将调用子类中的定义方法这相当于把父类中定义的那个完全相同的方法给覆盖了这也是面向对象编程的多态性的一种表现。
子类覆盖父类的方法时只能比父类抛出更少的异常或者是抛出父类抛出的异常的子异常因为子类可以解决父类的一些问题不能比父类有更多的问题。
子类方法的访问权限只能比父类的更大不能更小。
如果父类的方法是private类型那么子类则不存在覆盖的限制相当于子类中增加了一个全新的方法。
至于Overloaded的方法是否可以改变返回值的类型这个问题要看你倒底想问什么呢这个题目很模糊。
如果几个Overloaded的方法的参数列表不一样它们的返回者类型当然也可以不一样。
但我估计你想问的问题是如果两个方法的参数列表完全一样是否可以让它们的返回值不同来实现重载Overload。
这是不行的我们可以用反证法来说明这个问题因为我们有时候调用一个方法时也可以不定义返回结果变量即不要关心其返回结果例如我们调用map.remove(key)方法时虽然remove方法有返回值但是我们通常都不会定义接收返回结果的变量这时候假设该类中有两个名称和参数列表完全相同的方法仅仅是返回类型不同java就无法确定编程者倒底是想调用哪个方法了因为它无法通过返回结果类型来判断。
override可以翻译为覆盖从字面就可以知道它是覆盖了一个方法并且对其重写以求达到不同的作用。
对我们来说最熟悉的覆盖就是对接口方法的实现在接口中一般只是对方法进行了声明而我们在实现时就需要实现接口声明的所有方法。
除了这个典型的用法以外我们在继承中也可能会在子类覆盖父类中的方法。
在覆盖要注意以下的几点
覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配才能达到覆盖的效果
覆盖的方法的返回值必须和被覆盖的方法的返回一致
覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致或者是其子类
被覆盖的方法不能为private否则在其子类中只是新定义了一个方法并没有对其进行覆盖。
Overload对我们来说可能比较熟悉可以翻译为重载它是指我们可以定义一些名称相同的方法通过定义不同的输入参数来区分这些方法然后再调用时VM就会根据不同的参数样式来选择合适的方法执行。
在使用重载要注意以下的几点
在使用重载时只能通过不同的参数样式。
例如不同的参数类型不同的参数个数不同的参数顺序当然同一方法内的几个参数类型必须不一样例如可以是fun(int,float)但是不能为fun(int,int)
不能通过访问权限、返回类型、抛出的异常进行重载
方法的异常类型和数目不会对重载造成影响
对于继承来说如果某一方法在父类中是访问权限是priavte那么就不能在子类对其进行重载如果定义的话也只是定义了一个新方法而不会达到重载的效果。
接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?抽象类中是否可以有静态的main方法接口可以继承接口。
抽象类可以实现(implements)接口抽象类可以继承具体类。
抽象类中可以有静态的main方法。
备注只要明白了接口和抽象类的本质和作用这些问题都很好回答你想想如果你是java语言的设计者你是否会提供这样的支持如果不提供的话有什么理由吗如果你没有道理不提供那答案就是肯定的了。
只要记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。
Java中实现多态的机制是什么靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象而程序调用的方法在运行期才动态绑定就是引用变量所指向的具体实例对象的方法也就是内存里正在运行的那个对象的方法而不是引用变量的类型中定义的方法。
abstractclass和interface语法上有什么区别?
抽象类可以有构造方法接口中不能有构造方法。
抽象类中可以有普通成员变量接口中没有普通成员变量
抽象类中可以包含非抽象的普通方法接口中的所有方法必须都是抽象的不能有非抽象的普通方法。
抽象类中的抽象方法的访问类型可以是publicprotected和默认类型,虽然eclipse下不报错但应该也不行但接口中的抽象方法只能是public类型的并且默认即为public abstract类型。
抽象类中可以包含静态方法接口中不能包含静态方法
抽象类和接口中都可以包含静态成员变量抽象类中的静态成员变量的访问类型可以任意但接口中定义的变量只能是publicstatic final类型并且默认即为publicstatic final类型。
一个类可以实现多个接口但只能继承一个抽象类。
abstract的method是否可同时是static,是否可同时是native是否可同时是synchronized?abstract的method不可以是static的因为抽象的方法是要被子类实现的而static与子类扯不上关系native方法表示该方法要用另外一种依赖平台的编程语言实现的不存在着被子类实现的问题所以它也不能是抽象的不能与abstract混用。
例如FileOutputSteam类要硬件打交道底层的实现用的是操作系统相关的api实现例如在windows用c语言实现的所以查看jdk的源代码可以发现FileOutputStream的open方法的定义如下private native void open(Stringname) throwsFileNotFoundException;如果我们要用java调用别人写的c语言函数我们是无法直接调用的我们需要按照java的要求写一个c语言的函数又我们的这个c语言函数去调用别人的c语言函数。
由于我们的c语言函数是按java的要求来写的我们这个c语言函数就可以与java对接上java那边的对接方式就是定义出与我们这个c函数相对应的方法java中对应的方法不需要写具体的代码但需要在前面声明native。
关于synchronized与abstract合用的问题我觉得也不行因为在我几年的学习和开发中从来没见到过这种情况并且我觉得synchronized应该是作用在一个具体的方法上才有意义。
而且方法上的synchronized同步所使用的同步锁对象是this而抽象方法上无法确定this是什么。
内部类可以引用它的包含类的成员吗有没有什么限制完全可以。
如果不是静态内部类那没有什么限制如果你把静态嵌套类当作内部类的一种特例那在这种情况下不可以访问外部类的普通成员变量而只能访问外部类中的静态成员例如下面的代码class Outer{static int x;static class Inner{voidtest(){syso(x);}}}
String s Hello;s s world!;这两行代码执行后原始的String对象中的内容到底变了没有没有。
因为String被设计成不可变(immutable)类所以它的所有对象都是不可变对象。
在这段代码中s原先指向一个String对象内容是 Hello然后我们对s进行了操作那么s所指向的那个对象是否发生了改变呢答案是没有。
这时s不指向原来那个对象了而指向了另一个 String对象内容为Hello world!原来那个对象还存在于内存之中只是s这个引用变量不再指向它了。
通过上面的说明我们很容易导出另一个结论如果经常对字符串进行各种各样的修改或者说不可预见的修改那么使用String来代表字符串的话会引起很大的内存开销。
因为String对象建立之后不能再改变所以对于每一个不同的字符串都需要一个String对象来表示。
这时应该考虑使用StringBuffer类它允许修改而不是每个不同的字符串都要生成一个新的对象。
并且这两种类的对象转换十分容易。
同时我们还可以知道如果要使用内容相同的字符串不必每次都new一个String。
例如我们要在构造器中对一个名叫s的String引用变量进行初始化把它设置为初始值应当这样做public class Demo {private String s;...public Demo {s Initial Value;}...}而非s new String(Initial Value);后者每次都会调用构造器生成新对象性能低下且内存开销大并且没有意义因为String对象不可改变所以对于内容相同的字符串只要一个String对象来表示就可以了。
也就说多次调用上面的构造器创建多个对象他们的 String类型属性s都指向同一个对象。
上面的结论还基于这样一个事实对于字符串常量如果内容相同Java认为它们代表同一个String对象。
而用关键字new调用构造器总是会创建一个新的对象无论内容是否相同。
至于为什么要把String类设计成不可变类是它的用途决定的。
其实不只String很多Java标准类库中的类都是不可变的。
在开发一个系统的时候我们有时候也需要设计不可变类来传递一组相关的值这也是面向对象思想的体现。
不可变类有一些优点比如因为它的对象是只读的所以多线程并发访问也不会有任何问题。
当然也有一些缺点比如每个不同的状态都要一个对象来代表可能会造成性能上的问题。
所以Java标准类库还提供了一个可变版本即StringBuffer。
ArrayList和Vector的区别这两个类都实现了List接口List接口继承了Collection接口他们都是有序集合即存储在这两个集合中的元素的位置都是有顺序的相当于一种动态的数组我们以后可以按位置索引号取出某个元素并且其中的数据是允许重复的这是与HashSet之类的集合的最大不同处HashSet之类的集合不可以按索引号去检索其中的元素也不允许有重复的元素。
ArrayList与Vector的区别主要包括两个方面.1同步性Vector是线程安全的也就是说是它的方法之间是线程同步的而ArrayList是线程序不安全的它的方法之间是线程不同步的。
如果只有一个线程会访问到集合那最好是使用ArrayList因为它不考虑线程安全效率会高些如果有多个线程会访问到集合那最好是使用Vector因为不需要我们自己再去考虑和编写线程安全的代码。
2数据增长ArrayList与Vector都有一个初始的容量大小当存储进它们里面的元素的个数超过了容量时就需要增加ArrayList与Vector的存储空间每次要增加存储空间时不是只增加一个存储单元而是增加多个存储单元每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。
Vector默认增长为原来两倍而ArrayList的增长策略在文档中没有明确规定从源代码看到的是增长为原来的
5倍。
ArrayList与Vector都可以设置初始的空间大小Vector还可以设置增长的空间大小而ArrayList没有提供设置增长空间的方法。
总结即Vector增长原来的一倍ArrayList增加原来的
5倍。
HashMap和Hashtable的区别HashMap是Hashtable的轻量级实现非线程安全的实现他们都完成了Map接口主要区别在于HashMap允许空null键值key,由于非线程安全在只有一个线程访问的情况下效率要高于Hashtable。
HashMap允许将null作为一个entry的key或者value而Hashtable不允许。
HashMap把Hashtable的contains方法去掉了改成containsvalue和containsKey。
因为contains方法容易让人引起误解。
Hashtable继承自Dictionary类而HashMap是Java
2引进的Map interface的一个实现。
最大的不同是Hashtable的方法是Synchronize的而HashMap不是在多个线程访问Hashtable时不需要自己为它的方法实现同步而HashMap就必须为之提供同步。
就HashMap与HashTable主要从三方面来说。
历史原因:Hashtable是基于陈旧的Dictionary类的HashMap是Java
2引进的Map接口的一个实现
同步性:Hashtable是线程安全的也就是说是同步的而HashMap是线程序不安全的不是同步的
值只有HashMap可以让你将空值作为一个表的条目的key或value
List和 Map区别?一个是存储单列数据的集合另一个是存储键和值这样的双列数据的集合List中存储的数据是有顺序并且允许重复Map中存储的数据是没有顺序的其键是不能重复的它的值是可以有重复的。
List,Set, Map是否继承自Collection接口?ListSet是Map不是
List、Map、Set三个接口存取元素时各有什么特点这样的题比较考水平两个方面的水平一是要真正明白这些内容二是要有较强的
总结和表述能力。
首先List与Set具有相似性它们都是单列元素的集合所以它们有一个共同的父接口叫Collection。
Set里面不允许有重复的元素即不能有两个相等注意不是仅仅是相同的对象即假设Set集合中有了一个A对象现在我要向Set集合再存入一个B对象但B对象与A对象equals相等则B对象存储不进去所以Set集合的add方法有一个boolean的返回值当集合中没有某个元素此时add方法可成功加入该元素时则返回true当集合含有与某个元素equals相等的元素时此时add方法无法加入该元素返回结果为false。
Set取元素时不能细说要取第几个只能以Iterator接口取得所有的元素再逐一遍历各个元素。
List表示有先后顺序的集合注意不是那种按年龄、按大小、按价格之类的排序。
当我们多次调用add(Obje)方法时每次加入的对象就像火车站买票有排队顺序一样按先来后到的顺序排序。
有时候也可以插队即调用add(intindex,Obj e)方法就可以指定当前对象在集合中的存放位置。
一个对象可以被反复存储进List中每调用一次add方法这个对象就被插入进集合中一次其实并不是把这个对象本身存储进了集合中而是在集合中用一个索引变量指向这个对象当这个对象被add多次时即相当于集合中有多个索引指向了这个对象如图x所示。
List除了可以用Iterator接口取得所有的元素再逐一遍历各个元素之外还可以调用get(index i)来明确说明取第几个。
Map与List和Set不同它是双列的集合其中有put方法定义如下put(obj key,obj value)每次存储时要存储一对key/value不能存储重复的key这个重复的规则也是按equals比较相等。
取则可以根据key获得相应的value即get(Object key)返回值为key所对应的value。
另外也可以获得所有的key的结合还可以获得所有的value的结合还可以获得key和value组合成的Map.Entry对象的集合。
List以特定次序来持有元素可有重复元素。
Set无法拥有重复元素,内部排序。
Map保存key-value值value可多值。
说出ArrayList,Vector,LinkedList的存储性能和特性ArrayList和Vector都是使用数组方式存储数据此数组元素数大于实际存储的数据以便增加和插入元素它们都允许直接按序号索引元素但是插入元素要涉及数组元素移动等内存操作所以索引数据快而插入数据慢Vector由于使用了synchronized方法线程安全通常性能上较ArrayList差。
而LinkedList使用双向链表实现存储按序号索引数据需要进行前向或后向遍历索引就变慢了但是插入数据时只需要记录本项的前后项即可所以插入速度较快。
LinkedList也是线程不安全的LinkedList提供了一些方法使得LinkedList可以被当作堆栈和队列来使用。
去掉一个Vector集合中重复的元素Vector newVector new Vector();For (int i0;ivector.size();i){Object obj vector.get(i);if(!newVector.contains(obj);newVector.add(obj);}还有一种简单的方式利用了Set不允许重复元素HashSetset new HashSet(vector);
Collection和Collections的区别。
Collection是集合类的上级接口继承他的接口主要有Set和List.Collections是针对集合类的一个帮助类他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
Set里的元素是不能重复的那么用什么方法来区分重复与否呢?是用还是equals()?它们有何区别?Set里的元素是不能重复的元素重复与否是使用equals()方法进行判断的。
和equal区别也是考烂了的题这里说一下操作符专门用来比较两个变量的值是否相等也就是用于比较变量所对应的内存中所存储的数值是否相同要比较两个基本类型的数据或两个引用变量是否相等只能用操作符。
equals方法是用于比较两个独立对象的内容是否相同就好比去比较两个人的长相是否相同它比较的两个对象是独立的。
比如两条new语句创建了两个对象然后用a/b这两个变量分别指向了其中一个对象这是两个不同的对象它们的首地址是不同的即a和b中存储的数值是不相同的所以表达式ab将返回false而这两个对象中的内容是相同的所以表达式a.equals(b)将返回true。
你所知道的集合类都有哪些主要方法最常用的集合类是 List 和 Map。
List的具体实现包括 ArrayList和 Vector它们是可变大小的列表比较适合构建、存储和操作任何类型对象的元素列表。
List适用于按数值索引访问元素的情形。
Map 提供了一个更通用的元素存储方法。
Map集合类用于存储元素对称作键和值其中每个键映射到一个值。
它们都有增删改查的方法。
对于set大概的方法是add,remove, contains等对于map大概的方法就是put,removecontains等List类会有get(int index)这样的方法因为它可以按顺序取元素而set类中没有get(int index)这样的方法。
List和set都可以迭代出所有元素迭代时先要得到一个iterator对象所以set和list类都有一个iterator方法用于返回那个iterator对象。
map可以返回三个集合一个是返回所有的key的集合另外一个返回的是所有value的集合再一个返回的key和value组合成的EntrySet对象的集合map也有get方法参数是key返回值是key对应的value这个自由发挥也不是考记方法的能力这些编程过程中会有提示结合他们三者的不同说一下用法就行。