java的基本程序设计结构

2021/4/28 22:29:06

本文主要是介绍java的基本程序设计结构,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

package hello;

public class FirstSample
{
    public static void main(String[]args)
    {
        System.out.println("Hello World!");
    }
}

源代码的文件名必须与公共类的文件名相同。
main方法必须声明为public
如果希望在终止程序时返回其他代码, 需要调用System.exit方法。
C#中文件注释为///, java中文件注释为以/**开始, */结束。

数据类型

整型

int, short, long, byte(1字节)
前缀加上0b可表示二进制数

浮点类型

float, double
有三个表示出错的浮点数值:

  1. Double.POSITIVE_INFINITY 正无穷大
  2. Double.NEGATIVE_INFINITY 负无穷大
  3. Double.NaN 不是一个数字

不能用如下语句判断:
if (x == Double.NaN)
所有非数值的值都认为是不相等的
可以使用

if (Double.isNaN(x))

char类型

java中char类型描述了UTF-16编码中的一个代码单元(code unit)

boolean 类型

只有true, false两个值

变量

在c++中, int i = 10 是一个定义
而 extern int i 是一个声明
java中不区分声明和定义

常量

java中用关键词final指示常量

运算符

对于浮点运算, 可在方法之前使用strictfp关键字标记, 使其使用严格的浮点运算

public static strictfp void main(String args[])

数学函数与变量

Math类中可以调用各种数学函数

public class FirstSample
{
    public static void main(String[]args)
    {
        double x = 4;
        double y = Math.sqrt(x);
        System.out.println(y);
    }
}

floorMod解决了负数取余的问题.

floorMod(position + adjustment, 12)(对于负除数, floorMod仍会得到负数结果)

Math.sin
Math.cos
Math.tan
Math.atan
Math.atan2
Math.exp
Math.log
Math.log10
Math.PI
Math.E

对于这些默认定义的类, 可以使用静态引入

import static java.lang.Math.*;
import static java.lang.Math.*;

public class FirstSample
{
    public static void main(String[]args)
    {
        double x = 4;
        double y = sqrt(x);
        System.out.println(y);
    }
}

Math类中, 所有的方法都使用计算机浮点单元中的例程, 如果得到一个准确的结果更重要, 那么应该使用StrictMath类, 使用fdlibm实现算法, 以确保在所有平台得到相同的结果。

数值类型之间的转换

int转换成double类型不会损失精度

强制类型转换

double x= 9.997;
int nx = (int)x;

对浮点数进行舍入运算用Math.round方法

double x = 9.997;
int nx = (int) Math.round(x);

round方法返回的结果是long类型, 仍需要强制类型转换

位运算符

运算符>>>会用0填充高位, 而>> 会用符号位填充高位

枚举类型

enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE};
Size t = Size.MEDIUM;

字符串

String e = "";   		//an empty string
String greeting = "Hello";

子串

String类中的substring方法可以从一个较大的字符串中提取出来一个子串

String greeting = "Hello";
String s = greeting.substring(0, 3);

创建s为由字符“Hel”组成的字符串。

拼接

java允许使用+号进行字符串的拼接。

不可变字符串

String类中没有提供修改字符串的方法, java文档中称String类对象为不可变字符串, 不过可以通过修改字符串变量, 使其引用其它字符串。

greeting = greeting.substring(0, 3) + "p!";

java中字符串相当于char* 指针.

检测字符串是否相等

使用equals方法

s.equals(t)

相等返回true, 否则返回false

java中的compareTo则完全与C中的strcmp类似

if (greeting.compareTo("Hello") == 0)...

空串和NULL串

空串是长度为0的字符串, 可调用如下代码进行检查

if (str.length() == 0)
或
if (str.equals(""))

null串表示目前没有任何对象与该变量关联
判断使用如下代码:

is(str == null)

码点与代码单元

大多数常用Unicode字符使用一个代码单元就可以表示, 而辅助单元需要一对代码单元
实际的码点数量可以调用

String greeting = "Hello";
int cpCount = greeting.codePointCount(0, greeting, length());

调用s.charAt(n)将返回位置n的代码单元

char first = greeting.charAt(0);
char last = greeting.charAt(4);

要想得到第i个码点

int index = greeting.offsetByCodePoints(0, i);   // 偏移i个码点
int cp = greeting.codePointAt(index);

在这里插入图片描述
该字符需要两个代码单元, 调用charAt()时请注意

如果想遍历一个字符串, 并依次查看每一个码点, 可使用如下代码

int cp = sentence.codePointAt(i);
if(Character.isSupplementaryCodePoing(cp))  i += 2;
else i++;

使用如下语句实现回退操作:

i--;
if (character.isSurrogate(sentence.charAt(i))) i--;
int cp = sentence.codePointAt(i);

更容易的方法是使用codePoints方法, 其生成一个int值的“流”, 每个int对应一个码点, 可以将其转换为一个数组, 再完成遍历。

int [] codePoints = str.codePoints().toArray();

反之, 可以使用构造函数

String str = new String(codePoints, 0, codePoints.length);

构建字符串

使用StringBuilder类可以用多个较短字符串来构建字符串

StringBuilder builder = new StringBuilder();
builder.append(ch);
builder.append(str);
String completedString = builder.toString();

StringBuffer和StringBuilder的API是相同的, 但StringBuffer支持多线程, 效率稍低。

输入输出

读取输入

首先需要构建一个Scanner对象, 并与System.in关联

Scanner in = new Scanner(System.in);
System.out.print("What is your name?");
String name = in.nextLine();

nextLine方法可以实现C中gets函数的效果。
要想读取一个整数, 则调用nextInt方法

System.out.print("How old are you?");
int age = in.nextInt();

要想读取浮点数, 则使用nextDouble方法。
Scaner类定义在java。util包中, 当时用的类不是定义在java.lang包中时, 必须使用import

import java.util.*;

public class InputTest
{
    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        // get first input
        System.out.print("What is your name?");
        String name = in.nextLine();

        //get second input
        System.out.print("How old are you?");
        int age = in.nextInt();
        System.out.println("Hello" + name + ". Next you will be " + (age + 1));

    }
}

Console类实现了从控制台读取密码

import java.io.Console.*;
Console cons = System.console();
String username = cons.readLine("User name:");
char[] passwd = cons.readPasswword("Password:");

格式化输出

用于printf的标志
+:打印正数和负数的符号
空格: 证书之前追加空格
0: 数字前面补0
-: 左对齐
( : 将负数括在括号内
, : 添加分组分隔符
#(对于f格式): 包含小数点
#(对于x或o格式): 添加前缀0x或0
$ : 给定被格式化的参数索引, 输出。(%1$d , %1 $x)
< : 格式化前面说明的字符(%d%<x)

可以使用静态的String。format方法创建一个格式化的字符串, 而不打印输出

String message = String.format("Hello, %s . Next you will be %d", name, age);
日期和时间的转换符
c : 完整的日期和时间 Mon Feb 09 18:05:19 PST 2015
F: ISO 8601 日期 2021-04-26
D: 美国格式时间 02/09/2019
T: 24小时时间 18:05:19
r: 12小时时间 06:05:19 pm
R: 24小时时间没有秒 18:05
Y: 4位数字的年(前面补0) 2021
y: 年的前两位数字(前面补零) 21
C: 年的后两个数字(前面补零) 20
B: 月的完整缩写 April
b或h: 月的缩写 Apr
m : 两位数字的月 04
d:两位数字的日(前面补0) 26
e: 两位数字的日(前面不补零) 26
A: 星期几的完整拼写 Monday
a: 星期几的缩写 Mon
j: 三位数的年中的日子(前面补0) 116
H: 两位数字的小时(前面补0) 18
k: 两位数字的小时(前面不补零) 18
I: 两位数字的小时(前面补0, 12进制) 06
l: 两位数字的小时 (前面不补零, 12进制) 6
M:两位数字的分钟 (前面补零) 05
S:两位数字的秒(前面补0) 19
L: 三位数字的毫秒(前面补0) 047
N: 九位数字的毫微秒(前面补0) 047000000
p: 上午或下午的标志 pm
z: 从GMT 起, RFC822数字位移 +0800
Z: 时区 CST
s: 从格林威治时间1970-01-01 00:00:00 起的秒数 1619435298
Q: 从格林威治时间1970-01-01 00:00:00起的毫秒数 1619435298047
            System.out.printf("%1$s %2$tB %2$te, %2$tY","Due Date:" , new Date());

还可以使用< 标志

System.out.printf("%s %tB %<te, %<tY","Due Date:" , new Date());

文件输入与输出

若想进行读取需要用一个File对象构造一个Scanner对象

Scanner in = new Scanner(Path.get("myfile.txt"), "UTF-8");

要想写入文件, 需要构造PrintWrite对象, 在构造器中, 只需要提供文件名

PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");

完成之后记得关闭文件流, 不然不会保存写入内容

out.close();

如果用一个不存在的文件构造Scanner, 或者用一个不能被创建的文件名构造一个PrintWriter, 那么就会发生异常, 这需要在main方法中用子句throws标记

public static void main(String[] args) throws IOException
{
	Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8");
	...
}

API

java.util.Scanner
Scanner(File source)
Constructs a new Scanner that produces values scanned from the specified file.
Scanner(String source)
Constructs a new Scanner that produces values scanned from the specified string.
java.io.PrintWriter
PrintWriter​(String fileName)
Creates a new PrintWriter, without automatic line flushing, with the specified file name.
java.nio.file.Paths
static Path get​(String first, String… more)
Converts a path string, or a sequence of strings that when joined form a path string, to a Path.

控制流程

与C语言不同, 不能在嵌套的块中声明同名变量

import java.util.*;
/**
* This program demonstrates a <code>while<code> loop.
* @author Cay Horstmann
*@writeby Saigyoujinexas
*/
public class Retirement
{
	public static void main(String[] args)
	{
		//read inputs
		Scanner in = new Scanner(System.in);
		System.out.print("How much money do you need to retire?");
		double goal = in.nextDouble();
		
		System.out.print("How much money will you contribute every year?");
		double payment = in.nextDouble();
		
		System.out.print("Interest rate in %:");
		double interestRate = in.nextDouble();
		
		double balance = 0;
		int years = 0;
		//update account balance while goal is not reached
		while (balance < goal)
		{
			//add this year's payment and interest
			balance += payment;
			double interest = balance * interestRate / 100;
			balance += interest;
			years++;
		}
		System.out.println("You can retire in " + years + " years.");
	}
}
import java.util.*;
/**
* This program demonstrates a <code>while<code> loop.
* @author Cay Horstmann
*@writeby Saigyoujinexas
*/
public class Retirement2
{
	public static void main(String[] args)
	{
		//read inputs
		Scanner in = new Scanner(System.in);
		
		System.out.print("How much money will you contribute every year?");
		double payment = in.nextDouble();
		
		System.out.print("Interest rate in %:");
		double interestRate = in.nextDouble();
		
		double balance = 0;
		int year = 0;
		
		String input;
		
		//update account balance while goal is not reached
		do
		{
			//add this year's payment and interest
			balance += payment;
			double interest = balance * interestRate / 100;
			balance += interest;
			
			year++;
			
			//print current balance
			System.out.printf("After year %d, your balance is %,.2f%n", year, balance);
			// ask if ready to retire and get input
			System.out.print("Ready to retire?(Y / N)");
			input = in.next();
		}while(input.equals("N"));
	}
}

对于switch循环, 必须有break语句
如果故意使用直通式(fallthrough)行为
在其外围方法加个标注 @SuppressWarnings(“fallthrough”)

中断控制流程语句

java提供了一种** 带标签的break语句**

Scanner in = new Scanner(system.in);
int n;
read_data:
while(...)
{
	for(...)
	{
		System.out.print("Enter a number >= 0");
		n = in.nextInt();
		if(n < 0)    	// should never happen-can't go on
			break read_data;
			//break out of read_data loop
			...
	}
}
// this statement is excuted immediately after the labeld break
if (n < 0)   		// check for bad situation
{
	//deal with bad situation
}
else
{
		//carry out normal processing
}

该标签可以应用到任何语句, 甚至是if语句或块语句中

label:
{
	...
	if (condition) break label;	// exit block
}

continue语句同样可带标签, 将跳转到与标签匹配的循环首部

大数值

java中两个很有用的类:BigInteger和Bigdecimal。
使用静态的valueOf方法可以将普通数值转换为大数值。

BigInteger a = BigInteger.valueOf(100);

不能使用运算符对大数值进行运算
需要使用add和multiply方法

BigInteger c = a.add(b);
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));

java不提供运算符重载功能

import java.math.*;
import java.util.*;

/**
 * This program uses big numbers to compute the odds of winning the grand prize in a lottery.
 * @author Cay Horstmann
 */

 public class BigIntegerTest
 {
     public static void main(String[] args)
     {
         Scanner in = new Scanner(System.in);
         System.out.print("How many numbers do you need to draw?");
         int k = in.nextInt();

         System.out.print("What is the highest number you can draw? ");
         int n = in.nextInt();
         /*
         *compute binomial coeffcient n*(n - 1)*(n-2)*(n-3)*...*(n-k+1)/(1*2*3*4*...*k)
         */
        BigInteger lotteryOdds = BigInteger.valueOf(1);
        for (int i = 1; i <= k; i++)
        {
            lotteryOdds = (lotteryOdds.multiply(BigInteger.valueOf(n - i + 1)).divide(BigInteger.valueOf(i)));
            System.out.println(lotteryOdds);
        }
            System.out.println("Your odds are 1 in " + lotteryOdds + ". Good luck!");

     }
 }

API

java.math.BigInteger
BigInteger add​(BigInteger val)
Returns a BigInteger whose value is (this+val).
BigInteger subtract​(BigInteger val)
Returns a BigInteger whose value is (this - val).
BigInteger multiply​(BigInteger val)
Returns a BigInteger whose value is (this * val).
BigInteger divide​(BigInteger val)
Returns a BigInteger whose value is (this / val).
BigInteger mod​(BigInteger m)
Returns a BigInteger whose value is (this mod m).
int compareTo​(BigInteger val)
Compares this BigInteger with the specified BigInteger.
static BigInteger valueOf​(long val)
Returns a BigInteger whose value is equal to that of the specified long.
java.math.BIgDecimal
BigDecimal add​(BigDecimal augend)
Returns a BigDecimal whose value is (this + augend), and whose scale is max(this.scale(), augend.scale()).
BigDecimal subtract​(BigDecimal subtrahend)
Returns a BigDecimal whose value is (this - subtrahend), and whose scale is max(this.scale(), subtrahend.scale()).
BigDecimal multiply​(BigDecimal multiplicand)
Returns a BigDecimal whose value is (this × multiplicand), and whose scale is (this.scale() + multiplicand.scale()).
BigDecimal divide​(BigDecimal divisor,RoundingMode roundingMode)
Returns a BigDecimal whose value is (this / divisor), and whose scale is this.scale().
int compareTo​(BigDecimal val)
Compares this BigDecimal with the specified BigDecimal.
static BigDecimal valueOf​(long val)
Translates a long value into a BigDecimal with a scale of zero.
static BigDecimal
valueOf​(long unscaledVal, int scale)
Translates a long unscaled value and an int scale into a BigDecimal.

数组

int a[];

该语句仅声明了变量还需要初始化

int [] a = new int[100];

创建字符数组时所有元素初始化为0。
获得数组元素数量可以使用array.length.

for (int i = 0; i < a.length; i++)
	System.out.println(a[i]);

for each循环

for (variable: collection) statement

定义一个变量用于暂存集合中的每一个元素并执行相应的语句
collection集合表达式必须是一个数组或者是一个实现了Iterable接口的类对象

for (int element: a)
	System.out.println(element);

等价于

for (int i = 0; i < a.length; i++)
	System.oout.println(a[i]);

但是for each 循环更为简洁
有个更简单的方式打印一个集合的所有元素, 即使用Arrays类中的toString 方法, 返回被放置在方括号内的数组元素, 用逗号分隔。

System.out.println(Arrays.toString(a));

数组初始化及匿名数组

int [] smallPrimes  = {2, 3, 5, 7, 11, 13 };

甚至可以申请初始化一个匿名的数组

new int[] {17, 19, 23, 29, 31, 37 }

使用这种语法可以重新初始化一个数组

smallPrimes = new int[] {17, 19, 23, 29, 31, 37 };

数组拷贝

此时两个变量**引用 **同一个数组

int [] luckNumbers = smallPrimes;
luckNumber[5] = 12   // now smallPrimes[5] is also  12

如果希望是进行拷贝而不是引用同一个数组, 使用Arrays类的copyOf方法

int [] copiedLuckNumbers = Arrays.copyOf(luckNumbers, 2 * luckNumbers.length);

第二个参数是新数组的长度, 故该方法可以用来增加数组长度

luckNumbers = Arrays.copyOf(luckNumbers, 2 * luckNumbers.length);

java基本上与C++分配在堆上的数组指针一致

命令行参数

 public class Message
 {
     public static void main(String[] args)
     {
         if (args.length == 0 || args[0].equals("-h"))
            System.out.print("Hello,");
        else if (args[0].equals("-g"))
            System.out.print("Goodbye.");
        for (int i = 1; i < args.length; i++)
            System.out.print(" " + args[i]);
        System.out.println("!");
     }
 }

在java程序中, 程序名不存在args数组中

数组排序

数值型数组使用Arrays类中的sort方法

int [] a= new int[1000];
...
Arrays.sort(a)

该方法使用优化的快速排序算法

import java.util.*;

/**
 * This program demonstrates array manipulation.
 * @author Cay Horstmann
 */

 public class LotteryDrawing
 {
        public static void main(String[] args)
        {
            Scanner in = new Scanner(System.in);
            System.out.print("How many  numbers do you need to draw? ");
            int k = in.nextInt();

            System.out.print("What is the highest number you can draw? ");
            int n = in.nextInt();

            //file an array with number 1, 2, 3, 4, ...
            int [] numbers = new int[n];
            for (int i = 0; i < numbers.length; i++)
            numbers[i] = i + 1;

            //draw k numbers and put them into a second array
            int[] result = new int[k];
            for (int i = 0; i < result.length; i++)
            {
                //make random index between 0 and n - 1
                int r = (int) (Math.random() * n);
                // pick the element at the random location
                result[i] = numbers[r];
                //move the last element into the random location
                numbers[r] = numbers[n - 1];
                n--;
            }
            // print the sorted array
            Arrays.sort(result);
            System.out.println("Bet the following combination. It will make you rich!");
            for (int r: result)
                System.out.println(r);
        }
 }

Math.random方法将生成一个0到1的浮点数。

API

java.util.Arrays
static String toString​(Type[] a)
Returns a string representation of the contents of the specified array.
Type could be int, short, byte, boolean, long, char, float, double or object
static Type[] copyOf​(Type [] original, int newLength)
Copies the specified array, truncating or padding with zeros (if necessary) so the copy has the specified length.
Type could be byte, short, int, long , boolean, char, float, double, T.
static boolean[] copyOfRange​(boolean[] original, int from, int to)
Copies the specified range of the specified array into a new array.
Type could be byte, short, int, long, boolean, char, float, double, T.
static void sort​(Type[] a, int fromIndex, int toIndex)
Sorts the specified range of the array into ascending order.
Type could be byte, short, int , long , boolean, char, float, double , T.
fromIndex and toIndex are optional.
static Type binarySearch​(Type[] a, int fromIndex, int toIndex, Type key)
Searches the specified array of bytes for the specified value using the binary search algorithm.
Type could be byte, short, int , long , boolean, char, float, double , T.
fromIndex and toIndex are optional.
static void fill​(Type[] a, int fromIndex, int toIndex, Type val)
Assigns the specified float value to each element of the specified range of the specified array of floats.
Type could be byte, short, int , long , boolean, char, float, double , object.
fromIndex and toIndex are optional.
static boolean equals​(Type[] a, int aFromIndex, int aToIndex, Type[] b, int bFromIndex, int bToIndex)
Returns true if the two specified arrays of shorts, over the specified ranges, are equal to one another.
Type could be byte, short, int , long , boolean, char, float, double , object, T.
aFromIndex, aToIndex, bFromIndex and bToIndex are optional.

多维数组

double [][] balances;

同样, 在初始化完成后才能使用

balances = new double[NYEARS][NRATES]
int magicSquare = 
{
	{16, 3, 2, 13},
	{5, 10, 11, 8},
	{9, 6, 7, 12},
	{4, 15, 14, 1}
};

for each 循环不能自动处理二维数组每个元素

for (double[] row: a)
	for (double value: row)
		do something with value

要想快速打印一个二维数组, 可以调用

System.out.println(Arrays.deepToString(a));
/**
 * This program shows how to store tabular data in a 2D array.
 * @author Cay Horstmann
 */
public class CompoundInterest
{
    public static void main(String[] args)
    {
        final double STARTRATE = 10;
        final int NRATES = 6;
        final int NYEARS = 10;

        //set interest rates to 10.....15%
        double[] interestRate = new double[NRATES];
        for (int j = 0; j < interestRate.length; j++)
            interestRate[j] = (STARTRATE + j) / 100.0;
        
        double [][] balances = new double[NYEARS][NRATES];

        //set initial balances to 10000
        for (int j = 0; j < balances[0].length; j++)
            balances[0][j] = 10000;

        //compute interest for future years
        for (int i = 1; i < balances.length; i++)
        {
            for (int j = 0; j < balances[i].length; j++)
            {
                //get last year's balances from previous now
                double oldBalance = balances[i - 1][j];

                //compute interest
                double interest = oldBalance * interestRate[j];

                //compute this year's balances
                balances[i][j] = oldBalance + interest;
            }
        }
        //print one row of interest rates
        for (int j = 0; j < interestRate.length; j++)
            System.out.printf("%9.0f%%", 100 * interestRate[j]);
        
        System.out.println();

        //print balance table
        for (double[] row: balances)
        {
            for (double b: row)
                System.out.printf("%10.2f", b);
            System.out.println();
        }
    }
}

不规则数组

java实际上没有多维数组, 多维数组被解释为数组的数组

int[][] odds = new int[NMAX + 1][];

for (int n = 0;  n <= NMAX; n++)
	odds[n] = new int[n + 1];

分配数组后, 就可以采用通常的方式进行访问

for (int n = 0; n < odds.length; n++)
	for (int k = 0; k < odds[i].length; k++)
	{
		//compute lotteryOdds;
		...
		odds[n][k] = lotteryOdds;
	}
double[][] balances = new double[10][6];

该声明等同于C++中

double** balances = new double*[10];
for (int i = 0; i < 10; i++)
	balances[i] = new double[6];

实例

杨辉三角打印

/**
 * This program demostrates a triangular array.
 * @author Cay Horstmann
 */

 public class lotteryArray
 {
     public static void main(String[] args)
     {
         final int NMAX = 10;
         //allocate triangular array
         int[][] odds = new int[NMAX + 1][];
         for (int n = 0; n <= NMAX; n++)
            odds[n] = new int[n + 1];

        //fill triangular array
        for(int n = 0; n < odds.length; n++)
            for(int k = 0; k < odds[n].length; k++)
            {
                /*
                *compute binomial coefficient n*(n-1)*(n-2)*...*(n-k+1)/(1*2*3*...*k)
                */
                int lotteryOdds = 1;
                for (int i = 1; i <= k; i++)
                lotteryOdds = lotteryOdds * (n-i + 1) / i;

                odds[n][k] = lotteryOdds;
            }

            //print triangular array
        for (int[] row: odds)
        {
            for (int odd : row)
                System.out.printf("%4d", odd);
            System.out.println();
        } 
     }
 }

算法优化:

/**
 * This program demostrates a triangular array.
 * @author Cay Horstmann
 */

 public class lotteryArray
 {
     public static void main(String[] args)
     {
         final int NMAX = 10;
         //allocate triangular array
         int[][] odds = new int[NMAX + 1][];
         for (int n = 0; n <= NMAX; n++)
         {
            odds[n] = new int[n + 1];
            odds[n][0] = 1;
            odds[n][n] = 1;
        }

        //fill triangular array
        for(int n = 1; n < odds.length; n++)
            for(int k = 1; k < odds[n].length - 1; k++)
                odds[n][k] = odds[n - 1][k - 1] + odds[n - 1][k];

            //print triangular array
        for (int[] row: odds)
        {
            for (int odd : row)
                System.out.printf("%4d", odd);
            System.out.println();
        } 
     }
 }


这篇关于java的基本程序设计结构的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程