JAVA语言基础知识
来源:互联网 发布:nginx requires gd 编辑:程序博客网 时间:2024/06/06 02:34
- 语言基础知识
- 变量variable
- 命名Naming
- 原始数据类型Primitive Data Types
- 默认值Default values
- 字面量Literals
- 默认值Default values
- 数组Arrays
- 声明一个变量来引用数组declaring a variable to refer to an Array
- 创建初始化以及访问数组creatinginitializingand accessing an Array
- 拷贝数组Copying Arrays
- 操作数组Array Manipulations
- 关于变量的小结
- 操作符operators
- 赋值算术一元操作符
- 等式关系条件运算符
- 表达式语句块expressionsstatementsand blocks
- 表达式Expression
- 语句
- 控制流程语句Control flow Statements
- if-then 和 if-then-else语句
- switch语句
- while 和 do-while语句
- for语句
- 分支语句branching statments
- 变量variable
语言基础知识
变量(variable)
在前面的课程中我们知道对象将它的状态存储在字段(fields)中:
int cadence = 0;
int speed = 0;
int gear = 1;
什么是对象的讨论中给大家引入了字段(fields),但是你们还可能仍有一些问题,例如:字段命名的规范和约定是什么?除了int,还有其他什么的数据类型?字段声明的时候需要赋予初始值么?假如字段声明时不赋初值那系统会自动赋予默认值么?在本章节中我们将讨论这些问题,但在讨论之前我们需要意识到一些专业术语之间的区别。在Java编程语言中,术语”field“、”variable“都用到过,这是一些编程新手困惑的来源,因为它们似乎指代同一样东西。
Java编程语言定义了一下几种类型的变量:
- 实例变量(非静态字段)。从技术上讲,对象将它们各自的状态存储在非静态字段(Non-Static Fields)中,也就是说字段的声明不加static关键字。非静态字段是人们所熟知的实例变量(Instance Variables),因为由同一个类创建出来的不同实例(对象)的成员属性(Fields values)是不同的。如一个自行车对象的currentSpeed与其他自行车对象的是无关的。
- 类变量(静态字段)。任何字段在声明时用静态(static)修饰词修饰的都是类变量(class variables),这是在告诉编译器,无论对某个类进行实例化多少次,该变量仅存一份(there si exactly one copy of this variable in existence)。例如代码static int numGears = 6,意思是说某个自行车类所创建的自行车对象都是6个档位的。此外用关键字final修饰将表示Gears的数量将不会改变。
- 本地变量(Local Variables)。这类似对象将状态存储于字段中,一个方法经常在本地变量中存储临时状态。声明一个本地变量和声明一个字段很类似(如,int count = 0)。没有一特殊的关键字来置顶一个变量为本地变量,决定因素完全来自变量所处的位置——方法的{}之间。像这样,本地变量只在方法内部可见,类内其他地方是无法访问到的。
- 参数(Parameters)。例如public static void main(String[] args)中的args就是main方法的参数。应该记住的最重要事情是参数(parameters)最会被归类为变量(variables)而不是字段(field)。
偶尔你也可能看到在文章中用到“成员”这个词。类型的字段、方法和嵌套类型统称其为成员。
命名(Naming)
每种编程语言都有它自己的一堆命名规则和约定,Java编程亦是如此。变量的命名的约定和规则如下:
- 变相是大小写敏感的。变量的命名要遵循regex=\^[a-zA-Z|$|_][a-zA-Z0-9],即以大小写字母或下划线或美元符号开始,组成元素为数字和字母,下划线和美元符号。一般不建议变量中包含美元符号、下划线。
- 变量的子集仍是数字、字母、下划线和美元符号。命名最好不是单词的缩写以便易于维护和阅读。要注意的是变量命名不能是保留字或者关键字。
- 如果组成变量的名称只包含一个单词,最好将它拼成小写形式。如果变量名称有多个单词,那么除第一单词的首字母小写外,确保每个单词的首字母大写,即驼峰命名法。如果是常量则应全为大写字母,如果常量由多个单词构成,单词之间用下划线连接,如static final int NUM_GEARS=6.
原始数据类型(Primitive Data Types)
Java语言是静态语言,这意味着变量要使用之前须得先声明。这涉及到声明变量的类型和名称,例如:
int gears = 1;
这样做是告诉你的程序,存在这样一个字段”gears“,它存放数值数据,初始值为1.变量的数据类型决定了它可能存储的值以及可执行的操作。除了int类型,Java编程语言提供了其他7种原始数据类型。这八种原始数据类型是:
除以上八种原始数据类型之外,Java编程语言通过java.lang.String提供了字符串。把字符串放在”“之内即可自动创建String对象,如String s = “this is a String”;String对象是不可变(immutable)的,意味着一旦创建将不可改变。
默认值(Default values)
声明一个字段时赋予一个值不总是必要的。字段声明时不初始化编译器将会赋予一个合理的默认值,默认值将会是0或者null,至于是什么将取决于数据类型。下面是各种数据类型对应的模式值:
备注:局部变量有些特殊。编译器绝不会为未初始化的局部变量赋予默认值。当你不能在声明局部变量时初始化它,确保在使用它之前进行赋值。假如访问未初始化的局部变量时,编译器会报错。
public void test(){ int count; System.out.println(a);}将会报错:variable count might not have been initialized
字面量(Literals)
你也许注意到初始化一个原始数据类型的变量是不需要new关键字的。原始类型是内置于语言中的特殊数据类型,它们不是从类中创建而来的对象。字面量是代表固定值的源码,即是说字面量的值直接就是源码所显示的那样,不需要通过任何计算。
数组(Arrays)
数组是一个容器对象(container object),它保存单一类型的数据。当数组创建时,它的长度就固定了。
数组内的每一项内容被称为元素(Element),通过数字索引访问它们。如上图所示,索引从0开始,以9结束。
class ArrayDemo { public static void main(String[] args) { // declares an array of integers int[] anArray; // allocates memory for 10 integers anArray = new int[10]; // initialize first element anArray[0] = 100; // initialize second element anArray[1] = 200; //... //print the first item in this array System.out.println("Element at index 0: "+ anArray[0]); System.out.println("Element at index 1: "+ anArray[1]); //... }} The output from this program is:Element at index 0: 100Element at index 1: 200//...
声明一个变量来引用数组(declaring a variable to refer to an Array)
上面一个例子声明的数组的方式如下:
// declares an array of integersint[] anArray;
和声明其他类型的变量一样,声明数组也由两部分组成:数组的类型和数组的名称。数组的类型写成type[],type指的是数据存放的数据类型。[]括号表明变量持有一个数组。和其他变量类型一样,声明不会实际创建一个数组,这仅仅简单地告诉编译器这个变量将存放某种类型的数据。类似地,你可以用其他类型声明一个数组:
byte[] anArrayOfBytes;short[] anArrayOfShorts;long[] anArrayOfLongs;float[] anArrayOfFloats;double[] anArrayOfDoubles;boolean[] anArrayOfBooleans;char[] anArrayOfChars;String[] anArrayOfStrings;
当然你也可以那么声明:
// this form is discouragedfloat anArrayOfFloats[];
创建,初始化以及访问数组(creating,initializing,and accessing an Array)
使用new操作来创建一个数组。
// create an array of integersanArray = new int[10];
接下来几行是给数组赋值:
anArray[0] = 100; // initialize first elementanArray[1] = 200; // initialize second elementanArray[2] = 300; // and so forth
访问数组是通过数字索引:
System.out.println("Element 1 at index 0: " + anArray[0]);System.out.println("Element 2 at index 1: " + anArray[1]);System.out.println("Element 3 at index 2: " + anArray[2]);
当然,你可以用以下方式来创建以及初始化一个数组:
int[] anArray = { 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
数组的大小取决于里面元素的个数。
你也可以通过使用多个[]定义多维数组,比如String[][] name.
class MultiDimArrayDemo { public static void main(String[] args) { String[][] names = { {"Mr. ", "Mrs. ", "Ms. "}, {"Smith", "Jones"} }; // Mr. Smith System.out.println(names[0][0] + names[1][0]); // Ms. Jones System.out.println(names[0][2] + names[1][1]); }}//The output from this program is:Mr. SmithMs. Jones
拷贝数组(Copying Arrays)
class ArrayCopyDemo { public static void main(String[] args) { char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' }; char[] copyTo = new char[7]; System.arraycopy(copyFrom, 2, copyTo, 0, 7); System.out.println(new String(copyTo)); }}//The output from this program is:caffein
操作数组(Array Manipulations)
在编程中,数组是一个有力而有用的概念。Java SE提供了对数组的一些常见操作,例如拷贝、搜索、排序等。这些操作是类java.util.Arrays提供的。
class ArrayCopyOfDemo { public static void main(String[] args) { char[] copyFrom = {'d', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd'}; char[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9); System.out.println(new String(copyTo)); }}
关于变量的小结
Java语言术语库中包含 “fields” 和 “variables”.
- 同一类的不同实例,其Instance variables (non-static fields) 是不同的.
- 字段声明时用static修饰词修饰的是Class variables (static fields); 无论类被实例化多少遍class variable只存在一份. 3. 局部变量在方法内部存放临时状态.
- 参数是提供给方法额外信息的变量(variable)。局部变量和参数总被归成 “variables” (而不是 “fields”).
当为字段和变量命名时,需要遵循一定的约定和规则。
- 八种原始数据类型是: byte, short, int, long, float, double, boolean, and char. java.lang.String类代表字符串。
- 编译器会为以上提高的数据类型赋予合理的默认值;然而,对于本地变量(局部变量)来说,默认值将不会被赋予.
- 字面量是源码所代表的固定的值,不需计算即可得出.数组是存储单一类型的变量,数组一旦创建,其长度将不会改变。
操作符(operators)
你已经学会了如何声明和初始化变量后,你可能想使用它们。学习Java编程怨言是一个好的起始点。运算符是在一个、两个或者三个操作数(operands)上执行具体操作的符号(symbol)。
在探索Java编程语言的操作符时,预先知道哪些运算符具有最高优先权(highest precedence)是非常有帮助的。下标所列举的运算符是按照优先权排序的,越靠近表格顶端的运算符具有越高的优先权。优先权更高的运算符先于优先权更低的执行。同一行的运算符具有同等的优先权,这时应该制定一个谁先执行的规则。除赋值运算符外,所有的运算符都是从左到右计算值;赋值运算符从右向左计算值。
在通用(general-purpose)编程中,某些运算符使用更频繁些;例如赋值运算符”=”比无符号又移运算符”>>>”更加常见。考虑到这一点,在接下来的讨论中将重点关注常用的运算符,最后才转向不常见的运算符。每一次讨论都附上代码,研究他们的输出内容将有助于你刚学的知识。
赋值、算术、一元操作符
最简单的赋值运算符
最常见的运算符就是赋值运算符”=”,它将右边的值赋给左边的操作数(operand):
int cadence = 0;
赋值运算符也可以用于给对象赋予对象引用。
算术运算符
Java编程语言提供了加(addition)、减(subtraction)、乘(multiplication)、和除(division)运算符。这些运算符你在基础数学上已经学过,但是”%”你可能感到陌生,这个运算符是将操作数除某个数然后返回其余数的意思。
下面的类ArithmeticDemo测试以上的运算符:
class ArithmeticDemo { public static void main (String[] args) { int result = 1 + 2; // result is now 3 System.out.println("1 + 2 = " + result); int original_result = result; result = result - 1; // result is now 2 System.out.println(original_result + " - 1 = " + result); original_result = result; result = result * 2; // result is now 4 System.out.println(original_result + " * 2 = " + result); original_result = result; result = result / 2; // result is now 2 System.out.println(original_result + " / 2 = " + result); original_result = result; result = result + 8; // result is now 10 System.out.println(original_result + " + 8 = " + result); original_result = result; result = result % 7; // result is now 3 System.out.println(original_result + " % 7 = " + result); }}This program prints the following:1 + 2 = 33 - 1 = 22 * 2 = 44 / 2 = 22 + 8 = 1010 % 7 = 3
可以将算术运算符和赋值运算符组合(combine)起来,以实现复合赋值(compound assignments),如x += 1.
+运算符用在字符串,则是拼接,如:
class ConcatDemo { public static void main(String[] args){ String firstString = "This is"; String secondString = " a concatenated string."; String thirdString = firstString+secondString; System.out.println(thirdString); }}outputThis is a concatenated string.
一元(unary)运算符
一元运算符只需要一个操作数;它们执行自增一、自减一、否定一个表达式(-1)、布尔值(!true)取反等操作。
UnaryDemo类测试一元运算符:
class UnaryDemo { public static void main(String[] args) { int result = +1; // result is now 1 System.out.println(result); result--; // result is now 0 System.out.println(result); result++; // result is now 1 System.out.println(result); result = -result; // result is now -1 System.out.println(result); boolean success = false; // false System.out.println(success); // true System.out.println(!success); }}
自增一和自减一可以放在操作数的前面也可以放于后面。区别是++result计算结果是result自增一,而result++计算结果是result本身。下面请看例子:
class PrePostDemo { public static void main(String[] args){ int i = 3; i++; // prints 4 System.out.println(i); ++i; // prints 5 System.out.println(i); // prints 6 System.out.println(++i); // prints 6 System.out.println(i++); // prints 7 System.out.println(i); }}
等式、关系、条件运算符
等式(Equality)和条件(Relational)运算符
等式和条件运算符表明一个操作数是否大于、小于、等于、或不等于另一个操作数。注意测试两个原始数据类型的变量是否相等是用”==”而不是”=”.
如:
class ComparisonDemo { public static void main(String[] args){ int value1 = 1; int value2 = 2; if(value1 == value2) System.out.println("value1 == value2"); if(value1 != value2) System.out.println("value1 != value2"); if(value1 > value2) System.out.println("value1 > value2"); if(value1 < value2) System.out.println("value1 < value2"); if(value1 <= value2) System.out.println("value1 <= value2"); }}Output:value1 != value2value1 < value2value1 <= value2
条件运算符(conditional operators)
这两个运算符具有短路(short-circuiting)特征,意味着第二个操作数的估算不一定会进行,而是在需要的时候才执行。
class ConditionalDemo1 { public static void main(String[] args){ int value1 = 1; int value2 = 2; if((value1 == 1) && (value2 == 2)) //只执行value1 == 1,因为已经true了 System.out.println("value1 is 1 AND value2 is 2"); if((value1 == 1) || (value2 == 1)) //只执行value1 == 1 System.out.println("value1 is 1 OR value2 is 1"); }}
class ConditionalDemo2 { public static void main(String[] args){ int value1 = 1; int value2 = 2; int result; boolean someCondition = true; result = someCondition ? value1 : value2; System.out.println(result); }}
三元运算符好处就是可读性比if-then-else强,结构紧凑。
比较运算符instanceof
instanceof运算符是将一个对象和另一个具体类型比较。你可以利用它来测试某个对象是否是某个类的实例、是否是某个子类的实例、是否是某个接口实现类的实例。
下面程序,定义了一个父类(Parent.java),一个简单的接口(MyInterface.java)和一个继承父类并实现接口的子类(Child.java):
class InstanceofDemo { public static void main(String[] args) { Parent obj1 = new Parent(); Parent obj2 = new Child(); System.out.println("obj1 instanceof Parent: " + (obj1 instanceof Parent)); System.out.println("obj1 instanceof Child: " + (obj1 instanceof Child)); System.out.println("obj1 instanceof MyInterface: " + (obj1 instanceof MyInterface)); System.out.println("obj2 instanceof Parent: " + (obj2 instanceof Parent)); System.out.println("obj2 instanceof Child: " + (obj2 instanceof Child)); System.out.println("obj2 instanceof MyInterface: " + (obj2 instanceof MyInterface)); }}class Parent {}class Child extends Parent implements MyInterface {}interface MyInterface {}Output:obj1 instanceof Parent: trueobj1 instanceof Child: falseobj1 instanceof MyInterface: falseobj2 instanceof Parent: trueobj2 instanceof Child: trueobj2 instanceof MyInterface: true
注意null是所有东西的实例。
移位运算符
class Test { /** * Java中,用前置只能表示八进制、十进制、十六进制 * 前置0:八进制 * 无任何前置:十进制(decimal) * 前置0x或0X: 十六进制(Hexadecimal) * * @param args */ public static void main(String[] args) { int octalNum = 010;//octal八进制 8 int hexNum = 0X10;//hex十六进制 16 int num = 10;//十进制 log("八进制%s转二进制:%s", octalNum, binary(octalNum)); log("十六进制%s转二进制:%s", hexNum, binary(hexNum)); log("十进制%s转二进制:%s", num, binary(num)); log(""); log("取非:~%s=%s", binary(octalNum), binary(~octalNum)); log("取或:%s|%s=%s", binary(octalNum), binary(num), binary(octalNum | num)); log("取与:%s&%s=%s", binary(octalNum), binary(num), binary(octalNum & num)); log("取异或:%s^%s=%s", binary(octalNum), binary(num), binary(octalNum ^ num)); log(""); log("左移2位:%s<<2=%s", binary(num), binary(num << 2)); log("右位2位:%s>>2=%s", binary(num), binary(num >> 2)); log("无符号右移2位:%s>>>2=%s", binary(num), binary(num >> 2)); } private static String binary(int num) { return Integer.toBinaryString(num); } public static void log(String format, Object... args) { System.out.println(String.format(format, args)); }}output八进制8转二进制:1000十六进制16转二进制:10000十进制10转二进制:1010取非:~1000=11111111111111111111111111110111取或:1000|1010=1010取与:1000&1010=1000取异或:1000^1010=10左移2位:1010<<2=101000右位2位:1010>>2=10无符号右移2位:1010>>>2=10
表达式,语句,块(expressions,statements,and blocks)
你已经掌握了变量和运算符,现在该是学习表达式、语句和块的时候了。运算符是表达式的组成部分,它扮演者计算的角色;表达式是语句的核心部分;用块来组织语句。
表达式(Expression)
表达式是由变量、运算符、方法调用组成的一个构造(a construct),它的职责是计算一个值。如:
int cadence = 0;anArray[0] = 100;System.out.println("Element 1 at index 0: " + anArray[0]);int result = 1 + 2; // result is now 3if (value1 == value2) System.out.println("value1 == value2");
表达式的返回结果依赖于在表达式中使用的变量类型。例如上述代码中表达式”cadence = 0”返回的是cadence的类型int。和你所看到的一样,表达式也可以返回其它的类型,如表达式”value1 == value2”就是返回boolean。
Java编程语言允许使用许多个不同的表达式来构成一个复合表达式,只要各个子表达式中的计算值相互匹配,如:
1 * 2 * 3
1*2*3这个表达式的顺序无关紧要,因为无论如何调用次序它们的值都是一样的。但是这并不符合所有的表达式,如:
x + y /100 //有歧义
最好用()来精确告知编译器哪个子表达式先运行,如:
(x + y ) /100 //无歧义,建议
这样的话,更加便于维护。
语句
statements大概与自然语言中的句子相同。一个语句是一个完整单元的操作。下面的表达式用分号可以将表达式转换成语句:
- 赋值表达式
- 自增/自减操作
- 方法调用
- 对象创建
这样的语句叫做表达式语句(expression statements),下面举一些例子:
// assignment statementaValue = 8933.234;// increment statementaValue++;// method invocation statementSystem.out.println("Hello World!");// object creation statementBicycle myBike = new Bicycle();
除表达式语句外,还有其他两种语句,他们分别是声明语句(declaration statements)、流语句(flow statements)。声明语句声明一个变量,如:
double aValue = 7843843.343;
块(Block)
将0个或者0个以上的语句放到{}中,就是一个块,如:
class BlockDemo { public static void main(String[] args) { boolean condition = true; if (condition) { // begin block 1 System.out.println("Condition is true."); } // end block one else { // begin block 2 System.out.println("Condition is false."); } // end block 2 }}
控制流程语句(Control flow Statements)
源代码内的语句通常是从上到下执行的。然而控制流语句通过使用决策(decision making)、循环和分支来分解执行流,使程序能够有条件地执行特殊的代码块。本节描述决策语句(if-then, if-then-else, switch),循环语句(for,while,do-while),分支语句(break,continue,return).
if-then 和 if-then-else语句
if-then语句
这是最基本的控制流程语句,假如某个测试条件成立则执行,如Bicycle.java中,自行车移动了才能刹车:
void applyBrakes() { // the "if" clause: bicycle must be moving if (isMoving){ // the "then" clause: decrease current speed currentSpeed--; }}
if-then-else语句
void applyBrakes() { if (isMoving) { currentSpeed--; } else { System.err.println("The bicycle has already stopped!"); } }
switch语句
有很多种执行路径的可能,switch接收的参数可以是byte、short、char、int、enumerated types,String和Character、Byte、Short、Integer.如:
public class SwitchDemo { public static void main(String[] args) { int month = 8; String monthString; switch (month) { case 1: monthString = "January"; break; case 2: monthString = "February"; break; //... default: monthString = "Invalid month"; break; } System.out.println(monthString); }}
while 和 do-while语句
区别是,do-while块内的语句至少执行一次。如:
class DoWhileDemo { public static void main(String[] args){ int count = 1; do { System.out.println("Count is: " + count); count++; } while (count < 11); }}
for语句
for语句提供一种在一系列值上迭代的紧凑方式。重复循环直到某个终止条件被满足的方式被开发者称为for循环,通常for语句可以描述如下:
for (initialization; termination; increment) { statement(s)}
- initialization表达式。循环的起始,只运行一次。- termination表达式:计算出的值为false,循环终止。- increment表达式:每次迭代,表达式增加一个步长值或者减去一个步长值。例子:```javaclass ForDemo { public static void main(String[] args){ for(int i=1; i<11; i++){ System.out.println("Count is: " + i); } }}<div class="se-preview-section-delimiter"></div>```java增强for循环(更加紧凑和易读):```javaclass EnhancedForDemo { public static void main(String[] args){ int[] numbers = {1,2,3,4,5,6,7,8,9,10}; for (int item : numbers) { System.out.println("Count is: " + item); } }}<div class="se-preview-section-delimiter"></div>
分支语句(branching statments)
break 语句
break语句有两种形式:标记和未标记(labeled,unlabeled),可以在for,while,do-while循环中使用。未标记举例如下:
class BreakDemo { public static void main(String[] args) { int[] arrayOfInts = { 32, 87, 3, 589, 12, 1076, 2000, 8, 622, 127 }; int searchfor = 12; int i; boolean foundIt = false; for (i = 0; i < arrayOfInts.length; i++) { if (arrayOfInts[i] == searchfor) { foundIt = true; break; //跳出本次循环 } } if (foundIt) { System.out.println("Found " + searchfor + " at index " + i); } else { System.out.println(searchfor + " not in the array"); } }}<div class="se-preview-section-delimiter"></div>
标记的举例如下:
lass BreakWithLabelDemo { public static void main(String[] args) { int[][] arrayOfInts = { { 32, 87, 3, 589 }, { 12, 1076, 2000, 8 }, { 622, 127, 77, 955 } }; int searchfor = 12; int i; int j = 0; boolean foundIt = false; search: for (i = 0; i < arrayOfInts.length; i++) { for (j = 0; j < arrayOfInts[i].length; j++) { if (arrayOfInts[i][j] == searchfor) { foundIt = true; break search; //不加search,则只能跳出内层循环 } } } if (foundIt) { System.out.println("Found " + searchfor + " at " + i + ", " + j); } else { System.out.println(searchfor + " not in the array"); } }}
continue语句
提过本次循环,直接进入下次循环。
return语句
两种形式,一种是return;另一种是return result;
- Java语言基础知识
- JAVA语言基础知识
- java语言基础知识
- java语言基础知识01
- 【Java语言】基础知识一
- JAVA语言基础知识总结
- Java语言基础知识
- java语言基础知识回顾
- 【Java基础】语言基础知识
- 语言基础知识(java)
- Java语言基础知识
- JAVA语言基础知识
- JAVA教程-Java语言基础知识
- Java基础知识-Java语言基础
- Java基础知识-Java语言基础
- Java基础知识-Java语言基础
- 第二讲 Java语言基础知识
- 第二讲 Java语言基础知识
- 【palindrome-partitioning】
- 通过浏览器访问百度的详细过程?
- 机器学习 深度学习用到的数学基础知识 标量、向量、矩阵和张量
- SQLserver关键字大全
- BFS、模拟:UVa1589/POJ4001/hdu4121-Xiangqi
- JAVA语言基础知识
- #13. Roman to Integer
- 视图控制器
- 加油站问题(贪心法)
- Angular4.0 安装 环境搭建及安装失败解决办法
- java基础之IO流--RandomAccessFile(也很特殊,直接继承自Object类)
- C++指针编程你要小心的陷阱——如何优雅的释放指针void*
- 为什么epoll比select和poll更高效
- python控制台输出颜色