JavaGuide之Java基本功(⼀)
Java⼊门
1.Java语⾔有哪些特点?
简单易学;
⾯向对象(封装,继承,多态);
平台⽆关性( Java 虚拟机实现平台⽆关性);
可靠性;
安全性;
⽀持多线程;
⽀持⽹络编程并且很⽅便( Java 语⾔诞⽣本⾝就是为简化⽹络编程设计的,因此 Java 语⾔不仅⽀持⽹络编程⽽且很⽅便);
编译与解释并存;
2.关于JVM JDK JRE
JVM
Java虚拟机(JVM)是运⾏Java字节码的虚拟机。Jvm有针对不同系统的特定实现(windows、linux、macos等),⽬的是使⽤相同的字节码,它们都会给出相同的结果。
什么是字节码?采⽤字节码的好处?
在Java中,JVM可以理解的代码就叫做字节码(即扩展名为.class的⽂件),它不⾯向任何特定的处理器,只⾯向虚拟机。Java通过字节码的⽅式,在⼀定程度上解决了传统解释型语⾔执⾏效率低的问题,同时⼜保留了解释型语⾔可移植的特点。所以java程序运⾏时⽐较⾼效,⽽且,由于字节码不针对某⼀种特定的机器,因此java⽆需重新编译便可在多种不同操作系统的计算机上运⾏。
java程序从源代码到运⾏的步骤
需要格外注意的是.class-->机器码这⼀步。在这⼀步JVM类加载器⾸先加载字节码⽂件,然后通过解释器逐⾏解释执⾏,这种⽅式的执⾏速度会⽐较慢。⽽且有些⽅法和代码块是经常被调⽤的(热点代码),所以后⾯引进了JIT编译器,⽽JIT属于运⾏时编译。当JIT编译器完成第⼀次编译后,其会将字节码对应的机器码保存下来,下次可以直接使⽤。⽽我们知道,机器码的运⾏效率肯定⾼于java解释
器的。这也解释了我们为什么经常会说java是编译与解释共存的语⾔。HotSpot 采⽤了惰性评估(Lazy Evaluation)的做法,根据⼆⼋定律,消耗⼤部分系统资源的只有那⼀⼩部分的代码(热点代码),⽽这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执⾏的情况收集信息并相应地做出⼀些优化,因此执⾏的次数越多,它的速度就越快。JDK 9 引⼊了⼀种新的编译模式
AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各⽅⾯的开销。JDK ⽀持分层编译和 AOT 协作使⽤。但是
,AOT 编译器的编译质量是肯定⽐不上 JIT 编译器的。
总结
Java 虚拟机(JVM)是运⾏ Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),⽬的是使⽤相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语⾔"⼀次编译,随处可以运⾏"的关键所在。
JDK和JRE
JDK 是 Java Development Kit,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的⼀切,还有编译器(javac)和⼯具(如 javadoc 和 jdb)。它能够创建和编译程序。
JRE 是 Java 运⾏时环境。它是运⾏已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的⼀些基础构件。但是,它不能⽤于创建新程序。
如果只是为了运⾏⼀下 Java 程序的话,那么你需要安装 JRE 就可以了。如果你需要进⾏⼀些 Java 编程⽅⾯的⼯作,那么你就需要安装 JDK 了。但是,这不是绝对的。有时,即使不打算在计算机上进⾏任何 Java 开发,仍然需要安装 JDK。例如,如果要使⽤ JSP 部署 Web 应⽤程序,那么从技术上讲,只是在应⽤程序服务器中运⾏ Java 程序。那你为什么需要 JDK 呢?因为应⽤程序服务器会将 JSP 转换为 Java servlet,并且需要使⽤ JDK 来编译 servlet。
3.Oracle JDK 和 OpenJDK 的对⽐
对于 Java 7,没什么关键的地⽅。OpenJDK 项⽬主要基于 Sun 捐赠的 HotSpot 源代码。此外,OpenJDK 被选为 Java 7 的参考实现,由 Oracle ⼯程师维护。关于 JVM,JDK,JRE 和 OpenJDK 之间的区别,Oracle 博客帖⼦在 2012 年有⼀个更详细的答案:
问:OpenJDK 存储库中的源代码与⽤于构建 Oracle JDK 的代码之间有什么区别?
答:⾮常接近 - 我们的 Oracle JDK 版本构建过程基于 OpenJDK 7 构建,只添加了⼏个部分,例如部署代码,其中包括 Oracle 的 Java 插件和 Java WebStart 的实现,以及⼀些封闭的源代码派对组件,
如图形光栅化器,⼀些开源的第三⽅组件,如 Rhino,以及⼀些零碎的东西,如附加⽂档或第三⽅字体。展望未来,我们的⽬的是开源 Oracle JDK 的所有部分,除了我们考虑商业功能的部分。
总结:
Oracle JDK ⼤概每 6 个⽉发⼀次主要版本,⽽ OpenJDK 版本⼤概每三个⽉发布⼀次。但这不是固定的,我觉得了解这个没啥⽤处。详情参见:。OpenJDK 是⼀个参考模型并且是完全开源的,⽽ Oracle JDK 是 OpenJDK 的⼀个实现,并不是完全开源的;
Oracle JDK ⽐ OpenJDK 更稳定。OpenJDK 和 Oracle JDK 的代码⼏乎相同,但 Oracle JDK 有更多的类和⼀些错误修复。因此,如果您想开发企业/商业软件,我建议您选择 Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些⼈提到在使⽤ OpenJDK 可能会遇到了许多应⽤程序崩溃的问题,但是,只需切换到 Oracle JDK 就可以解决问题;
在响应性和 JVM 性能⽅⾯,Oracle JDK 与 OpenJDK 相⽐提供了更好的性能;
Oracle JDK 不会为即将发布的版本提供长期⽀持,⽤户每次都必须通过更新到最新版本获得⽀持来获取最新版本;
Oracle JDK 根据⼆进制代码许可协议获得许可,⽽ OpenJDK 根据 GPL v2 许可获得许可。
4.Java和C++的区别?
都是⾯向对象的语⾔,都⽀持封装、继承和多态
Java 不提供指针来直接访问内存,程序内存更加安全
Java 的类是单继承的,C++ ⽀持多重继承;虽然 Java 的类不可以多继承,但是接⼝可以多继承。
Java 有⾃动内存管理机制,不需要程序员⼿动释放⽆⽤内存
在 C 语⾔中,字符串或字符数组最后都会有⼀个额外的字符'\0'来表⽰结束。但是,Java 语⾔中没有结束符这⼀概念。
java中⽆需结束符的原因(接上条最后⼀点)
Java⾥⾯⼀切都是对象,是对象的话,字符串肯定就有长度,即然有长度,编译器就可以确定要输出的字符个数,当然也就没有必要去浪费那1字节的空间⽤以标明字符串的结束了。⽐如,数组对象⾥有⼀个属性length,就是数组的长度,String类⾥⾯有⽅法length()可以确定字符串的长度,因此对于输出函数来说,有直接的⼤⼩可以判断字符串的边界,编译器就没必要再去浪费⼀个空间标识字符串的结束。
java字符串末尾空字符的处理
java和c通信的时候,由于c中的char中有结束符的,所以当java收到C发来的字符串时,后⾯往往会有若⼲空字符,如果不做处理的话,java会对其⼀并输出,为了将空字符处理掉不输出,可以采⽤字符串的trim()⽅法,或⾃⼰实现去掉尾部空字符的⽅法:
/**
* 截取掉C中之前的字符串。即只截取前的字符
*
* @param s:尾部带有空字符的java字符串
* @return
*
*/
public static String deletTailChar0(String s){
if(s == null){
return null;
}
char[] chars = s.toCharArray();
StringBuffer sb = new StringBuffer();
for(char c : chars){
Character ch = c;
if(0 == ch.hashCode()){ //如果到了字符串结束,则跳出循环
break;
}else{
sb.append(c);
}
}
String();
}
5.什么是 Java 程序的主类应⽤程序和⼩程序的主类有何不同?
⼀个程序中可以有多个类,但只能有⼀个类是主类。在 Java 应⽤程序中,这个主类是指包含 main()⽅法的类。⽽在 Java ⼩程序中,这个主类是⼀个继承⾃系统类 JApplet 或 Applet 的⼦类。应⽤程序的主类不⼀定要求是 public 类,但⼩程序的主类要求必须是 public 类。主类是 Java 程序执⾏的⼊⼝点。
6.Java 应⽤程序与⼩程序之间有哪些差别?
简单说应⽤程序是从主线程启动(也就是 main() ⽅法)。applet ⼩程序没有 main()⽅法,主要是嵌在浏览器页⾯上运⾏(调⽤init()或者run()来启动),嵌⼊浏览器这点跟 flash 的⼩游戏类似。
7.import java 和 javax 有什么区别?
刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来使⽤。然⽽随着时间的推移,javax 逐渐地扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包确实太⿇烦了,最终会破坏⼀堆现有的代码。因此,最终决定 javax 包将成为标准 API 的⼀部分。
所以,实际上 java 和 javax 没有区别。这都是⼀个名字。
8.为什么说 Java 语⾔"编译与解释并存"?
⾼级编程语⾔按照程序的执⾏⽅式分为编译型和解释型两种。简单来说,编译型语⾔是指编译器针对特定的操作系统将源代码⼀次性翻译成可被该平台执⾏的机器码;解释型语⾔是指解释器对源程序逐⾏解释成特定平台的机器码并⽴即执⾏。⽐如,你想阅读⼀本英⽂名著,你可以⼀个英⽂翻译⼈员帮助你阅读,有两种选择⽅式,你可以先等翻译⼈员将全本的英⽂名著(也就是源码)都翻译成汉语,再去阅读,也可以让翻译⼈员翻译⼀段,你在旁边阅读⼀段,慢慢把书读完。
Java 语⾔既具有编译型语⾔的特征,也具有解释型语⾔的特征,因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,⽣成字节码(*.class ⽂件),这种字节码必须由 Java 解释器来解释执⾏。因此,我们可以认为 Java 语⾔编译与解释并存。
Java语法
1.字符型常量和字符串常量的区别?
形式上: 字符常量是单引号引起的⼀个字符; 字符串常量是双引号引起的若⼲个字符
含义上: 字符常量相当于⼀个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表⼀个地址值(该字符串在内存中存放位置)
占内存⼤⼩字符常量只占 2 个字节; 字符串常量占若⼲个字节 (注意: char 在 Java 中占两个字节)
java 编程思想第四版:2.2.2 节
2.关于注释
Java 中的注释有三种:
单⾏注释
多⾏注释
⽂档注释。
在我们编写代码的时候,如果代码量⽐较少,我们⾃⼰或者团队其他成员还可以很轻易地看懂代码,但是当项⽬结构⼀旦复杂起来,我们就需要⽤到注释了。注释并不会执⾏,是我们程序员写给⾃⼰看的,注释是你的代码说明书,能够帮助看代码的⼈快速地理清代码之间的逻辑关系。因此,在写程序的时候随⼿加上注释是⼀个⾮常好的习惯。
《Clean Code》这本书明确指出:
代码的注释不是越详细越好。实际上好的代码本⾝就是注释,我们要尽量规范和美化⾃⼰的代码来减少不必要的注释。
若编程语⾔⾜够有表达⼒,就不需要注释,尽量通过代码来阐述。
举个例⼦:
去掉下⾯复杂的注释,只需要创建⼀个与注释所⾔同⼀事物的函数即可
// check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
应替换为
if (employee.isEligibleForFullBenefits())
3.标识符和关键字的区别是什么?
在我们编写程序的时候,需要⼤量地为程序、类、变量、⽅法等取名字,于是就有了标识符,简单来说,标识符就是⼀个名字。但是有⼀些标识符,Java 语⾔已经赋予了其特殊的含义,只能⽤于特定的地⽅,这种特殊的标识符就是关键字。因此,关键字是被赋予特殊含义的标识符。⽐如,在我们的⽇常⽣活中,"警察局"这个名字已经被赋予了特殊的含义,所以如果你开⼀家店,店的名字不能叫"警察局","警察局"就是我们⽇常⽣活中的关键字。
4. Java中有哪些常见的关键字?
访问控制private protected public
类,⽅法和变量修饰符abstract class extends final implements interface native
new static strictfp synchronized transient volatile
程序控制break continue return do while if else
for instanceof switch case default
错误处理try catch throw throws finally
包相关import package
基本类型boolean byte char int double float long
short null true false
变量引⽤super this void
保留字goto const
5.⾃增⾃减运算符
在写代码的过程中,常见的⼀种情况是需要某个整数类型变量增加 1 或减少 1,Java 提供了⼀种特殊的运算符,⽤于这种表达式,叫做⾃增运算符(++)和⾃减
运算符(--)。
++和--运算符可以放在操作数之前,也可以放在操作数之后,当运算符放在操作数之前时,先⾃增/减,再赋值;当运算符放在操作数之后时,先赋值,再⾃增/减。
例如,当"b=++a"时,先⾃增(⾃⼰增加 1),再赋值(赋值给 b);当"b=a++"时,先赋值(赋值给 b),再⾃增(⾃⼰增加 1)。也就是,++a 输出的是 a+1 的值,a++输出的是 a 值。⽤⼀句⼝诀就是:"符号在前就先加/减,符号在后就后加/减"。
6. continue、break、和return的区别是什么?
在循环结构中,当循环条件不满⾜或者循环次数达到要求时,循环会正常结束。但是,有时候可能需要在循环的过程中,当发⽣了某种条件之后,提前终⽌循环,这就需要⽤到下⾯⼏个关键词:
continue :指跳出当前的这⼀次循环,继续下⼀次循环。
break :指跳出整个循环体,继续执⾏循环下⾯的语句。
return ⽤于跳出所在⽅法,结束该⽅法的运⾏。return ⼀般有两种⽤法:
return; :直接使⽤ return 结束⽅法执⾏,⽤于没有返回值函数的⽅法
return value; :return ⼀个特定值,⽤于有返回值函数的⽅法
7. Java泛型了解么?什么是类型擦除?介绍⼀下常⽤的通配符?
Java 泛型(generics)是 JDK 5 中引⼊的⼀个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到⾮法的类型。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为⼀个参数。
Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,这也就是通常所说类型擦除。(此问题后续会单独写⼀⽚⽂章)
List<Integer> list = new ArrayList<>();
list.add(12);
//这⾥直接添加会报错
list.add("a");
Class<? extends List> clazz = Class();
Method add = DeclaredMethod("add", Object.class);
//但是通过反射添加,是可以的
add.invoke(list, "kl");
System.out.println(list)
泛型⼀般有三种使⽤⽅式:泛型类、泛型接⼝、泛型⽅法。
1.泛型类:
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常⽤于表⽰泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey(){
return key;
}
}
如何实例化泛型类:Generic<Integer> genericInteger = new Generic<Integer>(123456);
2.泛型接⼝:
public interface Generator<T> {
public T method();
}
实现泛型接⼝,不指定类型:
class GeneratorImpl<T> implements Generator<T>{
@Override
public T method() {
return null;
}
}
实现泛型接⼝,指定类型:
class GeneratorImpl<T> implements Generator<String>{
入门的java游戏小程序@Override
public String method() {
return "hello";
}
}
3.泛型⽅法:
public static < E > void printArray( E[] inputArray )
{
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
使⽤:
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3 };
String[] stringArray = { "Hello", "World" };
printArray( intArray );
printArray( stringArray );
常⽤的通配符为: T,E,K,V,?
表⽰不确定的 java 类型
T (type) 表⽰具体的⼀个java类型
K V (key value) 分别代表java键值中的Key Value E (element) 代表Element
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论