1. java语言特性
- 简单有效
- 可移植:java依靠JVM实现了程序和操作系统无关。
- 面向对象
- 解释型语言
- 适合分布式运算:使用java编写socket比任何语言都简单。
- 拥有较好的性能
由于java是编译型语言,比解释型语言执行慢一点,但是java采用如下两种机制:
(1) Java源程序编写完毕,先使用Java伪编译器编译成class字节码文件再解释执行。
(2) 提供了准实时编译器JIT,当需要更快的速度时,可以使用JIT编译器将字节码转换成机器码,然后将其缓冲下来,这样速更快。 - 具备多线程处理能力
- 是一种动态语言(依靠的是反射机制和动态字节码机制)
(1) 在Java语言中,使用反射可以简单,直观地查询任何对象在JVM中运行时的信息并执行其方法和属性;也可以将新增的对象直接通过反射插入到动态运行的JVM中。
(2) 通过动态字节码机制可以在JVM内存中自动生成一个字节码文件用来增强某个对象的功能,即可以动态的为任何目标类生成虚拟字节码class文件(常结合动态代理实现,动态生成虚拟代理的class文件存在内存中)。
2. Jdk1.5之后的新特性
2.1 可变参数
底层是动态数组,根据传递的参数个数开辟指定大小的数组接收参数。
可变参数允许方法接受0个到多个参数。注意可以传递0个,即不传递。
2.2 foreach输出
foreach循环遍历输出和for循环输出原理相同。
2.3 案例
package javase.demo03.array.lixinghua;
// Java新特性,方法的可变参数和foreach输出,对数组和集合有很好的支持;
// 注意:for循环输出,需要能够拿到集合或者数组中的下标,也就是数组或者集合必须提供根据下标获取值的方法,才能够根据i的变化遍历出所有的值;
// 而foreach不需要存在根据下标获取值的方法,只需要定义一个形式参数,采用 形式参数 : 集合(数组) 即可遍历。
public class Demo05ForeachAndChangedVar {
public static void main(String args[]) {
help(1, 2, 3, 4, 5, 6, 7);
help("wo", "shi", "zhao", "er", "hu");
// 除了上面分开传递多个可变参数外,也可以直接传递一个数组
help(new int[] { 1, 2, 3, 4, 5, 6, 7 });
}
// 方法的可变参数
public static void help(int... a) {
// foreach输出
for (int b : a) {
System.out.print(b + "、");
}
System.out.println();
}
// 方法的可变参数
public static void help(String... s) {
// for循环输出
for (int i = 0; i < s.length; i++) {
System.out.println(s[i]);
}
}
}
3. java 注释
3.1 单行注释
// :表示单行注释,以//开始,到行尾结束。
3.2 多行注释
/* 多行注释。 */
3.3 文档注释
/** 文档注释。 */
4. 输出语句
System.out.println();或者System.out.print();前者输出后直接换行,后者不换行。
- println()方法是PrintStream打印流中封装的方法。out是System类的一个属性,本质是PrintStream打印流的实例化对象。println()方法在PrintStream打印流内部被重载了多次,可以输出任何数据类型的变量值。
- 输出语句输出任何类型的变量,总是默认调用Object类的toString()方法将输出的变量转换成字符串进行显示,不管此时的变量是什么类型的。如果是引用类型,将转换成引用地址对应的字符串;如果是基本类型,则直接输出基本类型的值。所有类都是Object顶级类的子类,Object类中的toString()方法就是输出当前对象的引用地址或者基本类型的值。如果当前类继承Object类覆盖了Object类中的toString()方法,则默认调用自己实现的toString()方法。
- 注意:在java中,一般list、map、jsonObject、jsonArray等直接输出是json字符串和json数组字符串;String直接输出的是value串值,Enum直接输出的是枚举常量的名称。因为这些类内部都覆盖了Object类的toString()方法,根据了自己的业务场景输出不同的值。
5. 案例
package javase.demo01.se.lixinghua;
// java三种注释学习。
// Java中输出 HelloWorld 和 Java中的三种注释。
public class Demo01HelloWorld {
public static void main(String args[]) {
// Java中的单行注释
System.out.println("这是java中的单行注释");
/*
* Java中的多行注释
*/
System.out.println("这是java中的多行注释");
/**
* Java中的文档注释
*/
System.out.println("这是java中的文档注释");
System.out.println("HelloWorld!");
}
}
6. 深入java可变参数
6.1 可变参数的底层原理是啥?
实际我们从可变参数的形式上已经看出来了,它本质上是个数组。
如下:
package zeh.test.demo.com.kebiancanshu;
//功能描述 java可变参数
public class TestMain {
public static void main(String[] args) {
print("1", "2", "3");
}
public static void print(String... args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
运行后使用jad进行反编译查看编译器编译后的代码:
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetso
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: TestMain.java
package zeh.test.demo.com.kebiancanshu;
import java.io.PrintStream;
public class TestMain
{
public TestMain()
{
}
public static void main(String args[])
{
print(new String[] {
"1", "2", "3"
});
}
public static transient void print(String args[])
{
String as[] = args;
int i = as.length;
for(int j = 0; j < i; j++)
{
String arg = as[j];
System.out.println(arg);
}
}
}
结果分析:编译器替我们将可变参数替换成了对应的数组。
6.2 调用可变参数时,可以给定任意多个参数,也可以不给定参数
可以给定任意多参数,也可以不给定参数:
package zeh.test.demo.com.kebiancanshu;
// java可变参数
public class TestMain {
public static void main(String[] args) {
print("1", "2", "3");
print("1");
print();
}
public static void print(String... args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
6.4 如果代码中有固定参数的方法,则优先匹配固定参数的方法
如果类中有和可变参数同名的方法,但它的参数是固定的,则传入指定参数后,匹配的是固定参数的方法。
匹配固定参数的同名方法:
package zeh.test.demo.com.kebiancanshu;
// java可变参数
public class TestMain {
public static void main(String[] args) {
print("1", "2", "3");
print("1");
print();
// 优先匹配固定参数的方法
print("eric", "daisy");
}
public static void print(String... args) {
for (String arg : args) {
System.out.println(arg);
}
}
public static void print(String s1, String s2) {
System.out.println("s1 = " + s1 + ";s2 = " + s2);
}
}
测试结果:
1
2
3
1
s1 = eric;s2 = daisy
6.3 如果要调用的方法可以和两个或者多个可变参数方法匹配,编译器将报错
有过个可以匹配上的可变参数方法时,编译器会报错:
package zeh.test.demo.com.kebiancanshu;
// java可变参数
public class TestMain {
public static void main(String[] args) {
// 三个String参数可以和下面两个可变参数方法都匹配上,因此编译器报错,不知道调用哪一个
print("1", "2", "3");
// 一个String参数的不会报错,会调用第一个print
print("1");
// 没有参数的也不会报错,会调用第一个print
print();
// 传入两个String参数,编译器不知道执行哪个可变参数,会报错
print("eric", "daisy");
}
public static void print(String... args) {
for (String arg : args) {
System.out.println(arg);
}
}
public static void print(String s1, String s2,String... args) {
System.out.println("s1 = " + s1 + ";s2 = " + s2);
}
}
6.4 一个方法最多只能有一个可变参数,且只能放在形参最后,否则编译报错
一个方法只允许有一个可变参数,且只能放在形参最后:
package zeh.test.demo.com.kebiancanshu;
import java.util.Arrays;
// java可变参数
public class TestMain {
public static void main(String[] args) {
print("1", "2", "3");
print("eric", "daisy");
}
// 一个方法只能有一个可变参数,且指定放在形参最后
public static void print(String s1, String s2, String... args) {
System.out.println(s1);
System.out.println(s2);
System.out.println(Arrays.toString(args));
}
}
6.5 避免带有可变参数的方法进行重载
尽管允许重载可变参数的方法,但是很容易让调用方陷入误区。
如下案例,重载后的方法和可变参数的方法逻辑完全不同,因此对于调用方来说很容易搞错,他可能会认为传入两个参数的也是调用的可变参数的方法逻辑,但实际上不是。
避免重载带有可变参数的方法:
package zeh.test.demo.com.kebiancanshu;
import java.util.Arrays;
// java可变参数
public class TestMain {
public static void main(String[] args) {
// 当传入3个参数时,调用的是可变参数的方法
print("1", "2", "3");
// 当传入两个参数时,调用的是重载后的有固定两个形参的方法
print("eric", "daisy");
}
// 可变参数的方法
public static void print(String s1, String s2, String... args) {
System.out.println(s1);
System.out.println(s2);
System.out.println(Arrays.toString(args));
}
// 重载可变参数的方法
public static void print(String s1, String s2) {
System.out.println("helloworld" + s1 + s2);
}
}
6.5 向一个持有可变参数的传递可变参数时,可以直接传递一个空数组
既然可变参数底层是一个数组对象,因此,除了显式传递多个可变参数外,也可以直接构建一个数组对象传递进去。 请注意:如果直接传递一个数组对象,这个对象不建议为null值,可以设置一个空数组对象传递进去。一旦传递一个null值进去的话,如果服务方需要遍历可变参数列表,将会直接抛出一个空指针异常。
文档信息
- 本文作者:Marshall