Java 注释语句和新特性

2021/01/05 Java基础知识 共 5395 字,约 16 分钟
闷骚的程序员

1. java语言特性

  1. 简单有效
  2. 可移植:java依靠JVM实现了程序和操作系统无关。
  3. 面向对象
  4. 解释型语言
  5. 适合分布式运算:使用java编写socket比任何语言都简单。
  6. 拥有较好的性能
    由于java是编译型语言,比解释型语言执行慢一点,但是java采用如下两种机制:
    (1) Java源程序编写完毕,先使用Java伪编译器编译成class字节码文件再解释执行。
    (2) 提供了准实时编译器JIT,当需要更快的速度时,可以使用JIT编译器将字节码转换成机器码,然后将其缓冲下来,这样速更快。
  7. 具备多线程处理能力
  8. 是一种动态语言(依靠的是反射机制和动态字节码机制)
    (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();前者输出后直接换行,后者不换行。

  1. println()方法是PrintStream打印流中封装的方法。out是System类的一个属性,本质是PrintStream打印流的实例化对象。println()方法在PrintStream打印流内部被重载了多次,可以输出任何数据类型的变量值。
  2. 输出语句输出任何类型的变量,总是默认调用Object类的toString()方法将输出的变量转换成字符串进行显示,不管此时的变量是什么类型的。如果是引用类型,将转换成引用地址对应的字符串;如果是基本类型,则直接输出基本类型的值。所有类都是Object顶级类的子类,Object类中的toString()方法就是输出当前对象的引用地址或者基本类型的值。如果当前类继承Object类覆盖了Object类中的toString()方法,则默认调用自己实现的toString()方法。
  3. 注意:在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值进去的话,如果服务方需要遍历可变参数列表,将会直接抛出一个空指针异常。

文档信息

Search

    Table of Contents