Java基础复习(二):关键字、数据类型、强制转换、运算符
注释
1.单行注释:
//单行注释
2.多行注释:
/*
*多行注释
*/
3.文档注释:
/**
* 文档注释
*/
注意:代码本身就可以起到注释的作用,所以在命名时就尽量做到见名知意。
关键字和标识符
1.标识符:是用于给 Java 程序中变量、类、方法等命名的符号。
标识符要遵守以下规则:
(1)标识符可以由字母、数字、下划线(_)、美元符($)组成,不能包含 @、%、空格等其它特殊字符,不能以数字开头。
(2)标识符不能是 Java 关键字和保留字,但可以包含关键字和保留字。
(3)标识符是严格区分大小写的。
(4)标识符的命名最好做到见名知意。
2.Java中的关键字:
数据类型
数据类型分为 基本数据类型 和 引用数据类型 ,其中基本数据类型有8种,除这8种之外其他的为引用数据类型。
- 基本数据类型:
(1)深入理解一下基本数据类型及其包装类:
基本数据类型与包装类之间的转换其实是装箱和拆箱的过程。装箱:自动将基本数据类型转换为包装类;拆箱:自动将包装类转换为基本数据类型。而在具体实现上,装箱过程调用包装类中的valueOf方法实现,拆箱过程是包装类中的xxxValue方法(例如:Integer.intValue)实现。
(2)包装类常量池问题
Byte、Short、Integer、Long:[-128,127]
Character:[0,127]
Boolean:True/False
Float、Double没有实现常量池技术,所以每次创建的都是新的对象
由于valueOf实现的不同即常量池的不同,会导致创建对象的时候可能会创建新的对象,或者是使用常量池中的对象不再重新创建对象。
java8种基本类型的自动装箱代码实现:
//boolean原生类型自动装箱成Boolean
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
//byte原生类型自动装箱成Byte
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
//short原生类型自动装箱成Short
public static Short valueOf(short s) {
final int offset = 128;
int sAsInt = s;
if (sAsInt >= -128 && sAsInt <= 127) { // must cache
return ShortCache.cache[sAsInt + offset];
}
return new Short(s);
}
//char原生类型自动装箱成Character
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}
//int原生类型自动装箱成Integer
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
//long原生类型自动装箱成Long
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
//double原生类型自动装箱成Double
public static Double valueOf(double d) {
return new Double(d);
}
//float原生类型自动装箱成Float
public static Float valueOf(float f) {
return new Float(f);
}
Test:
//Test
public class Main{
public static void main(Strign[] args){
Integer i1=100;
Integer i2=100;
Integer i3=200;
Integer i4=200;
System.out.println(i1==i2);//true
System.out.println(i3==i4);//false
}
}
//是因为valueOf的具体实现,在创建对象时,数值在[-128,127]之间会返回之前创建过的对象。
(3)需要注意的是“+”等运算符对包装类对象不适用,所以会自动拆箱为基本数据类型后再运算
并且new +包装类 创建对象时一定会新建一个对象,不会调用已存在的对象。
public class Main{
public static void main(Strign[] args){
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
System.out.println("i1=i2 " + (i1 == i2)); //true
System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); //true
System.out.println("i1=i4 " + (i1 == i4)); //false
System.out.println("i4=i5 " + (i4 == i5)); //false
System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); //true
System.out.println("40=i5+i6 " + (40 == i5 + i6)); //true
}
}
//i4 == i5 + i6语句为true,是因为”+“对包装类不适用,要先对i5,i6拆箱再运算,变为i4==40;由于Integer对象无法与数值比较,所以再对i4拆箱,变为40==40,结果为true。
更详细解答请前往深入刨析Java中的装箱与拆箱
-
引用数据类型:数组、类、接口
Lambda表达式允许通过表达式来代替功能接口,所以可以看作为引用数据类型。Lambda表达式是Java 8中一个重要的新特性,lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体。 -
基本数据类型之间的转换:
(1)自动类型转换:不需要书写代码,由系统自动完成的类型转换。
规则一:byte—>char、short —> int —> long —> float —> double;
规则二:当把任何基本数据类型的值和字符串值(String)进行连接运算时(+),基本数据类型会自动转换为字符串型。
(2)强制类型转换:必须书写代码才能完成的类型转换。该类类型转换很可能存在精度的损失,所以必须书写相应的代码,并且能够忍受该种损失时才进行该类型的转换。当存在这个方向(double→float→long→int→short(char)→byte)的转换时,则必须使用代码进行强制转换
//自动类型转换:
System.out.println(‘a’+1+”hello!”)//结果:98hello! ;因为char型(‘a’)先转换为int型,变为97;再与1进行运算,变为98;接着遇到字符串转换为字符串型,输出98hello!
//强制类型转换:
double d = 3.10;
int n = (int)d;
泛型
Java泛型是jdk5引入的新特性,提供了编译时类型安全检测机制。就是将类型由原来的具体的类型参数化(类似于方法中的变量参数),此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
Java泛型只在编译期有效,泛型信息不会进入到运行时阶段。即泛型只会在编译时帮助判断Java语言使用正确性,而本质上都属于同一个类型,在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。(类型擦除)
import java.util.ArrayList;
public class Test {
public static void main(String []args) {
ArrayList<String> a = new ArrayList<String>(); //创建泛型
ArrayList b = new ArrayList();
Class c1 = a.getClass(); //获取泛型的类型
Class c2 = b.getClass();
System.out.println(c1 == c2); //输出true
}
}
Java的泛型是伪泛型,在编译期间所有的泛型信息就会被擦除掉;例如定义List<Object>
和List<String>
,在编译后都变成List
,JVM看到的只是List,附加信息看不到。也是Java泛型的实现方法:类型擦除,类型擦除后保留原始类型。
详细类型擦除解答:Java泛型类型擦除及类型擦除带来的问题
注意:
(1)泛型类型变量不能是基本数据类型,可以是基本数据类型的包装类或引用数据类型或自定义类型。
(2)不能对确切的泛型类型使用instanceof操作。
if(ex_num instanceof Generic<Number>){ }//编译会报错
泛型的使用:
(1)泛型类:
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
//key这个成员变量的类型为T,T的类型由外部指定
private T key;
public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
this.key = key;
}
public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
return key;
}
}
如何实例化:
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(123456);
//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("key_vlaue");
.
(2)泛型接口:
//定义一个泛型接口
public interface Generator<T> {
public T next();
}
//实现泛型接口,不指定类型
class GeneratorImpl<T> implements Generator<T>{
@Override
public T method(){
return null;
}
}
//实现泛型接口,指定类型
class GeneratorImpl<T> implements Generator<String>{
@Override
public String method(){
return "hello";
}
}
.
(3)泛型方法:
public static <T> void show(T t){...}
.
(4)泛型的通配符:
- ?:表示不确定的Java类型
- T:表示具体的一个Java类型
- K V:表示Java键值中的Key和Value
- E:代表Element
上边界通配符(<? extends E>):List<? extends Animal>
作为一个方法的形参时,实际操作类型只能使用Animal的子类和本身(List<Dog>
或List<Animal>
)
下边界通配符(<? super E>):List<? super Dog>
作为一个方法的形参时,实际操作类型只能使用Dog的父类和本身(List<Animal>
或List<Dog>
)
常量和变量
-
常量:通常有字符串常量(双引号表示)、字符常量(点引号表示)、整数常量、浮点数常量、布尔常量(true/false)、空常量(null,需注意的是空常量不能直接打印)
字符串常量和字符常量的区别:
1.形式上:字符型常量:单引号引起;字符串常量:双引号引起。
2.含义上:字符常量相当于一个整型值(ASCII值),可以参与表达式运算;字符串常量代表一个地址值,在内存中存放的位置。
3.内存大小:字符常量:2字节;字符串常量:若干字节。 -
变量:可分为局部变量和成员变量
成员变量和局部变量的区别:
(1)语法形式上:成员变量是属于类的,在整个类都可以使用,局部变量是方法中定义的变量,只能在方法内部使用。成员变量可以被public、private、static等修饰符修饰,局部变量不可以,但两者都可以被final修饰。
(2)存储方式上:局部变量存储在栈中;成员变量存储在堆中。
(3)生命周期上:成员变量随着对象的创建而存在;局部变量随着方法的调用而自动消失
(4)初值:成员变量如果没有赋值,会有默认值,自动以数据类型的默认值而赋值;局部变量不会自动赋值。
命名方式:
1.包名:所有字母小写;xxxyyyzzz
2. 类名、接口名:所有单词的首字母大写;XxxYyyZzz
3. 变量名、方法名:第一个单词首字母小写,其他首字母大写;xxxYyyZzz
4. 常量名:所有字母都大写,单词之间用下划线 ;XXX_YYY_ZZZ
注意:命名时不可以使用关键字和保留字。
运算符
1.算术运算符(+、-、*、/、%、++、- -)
(1)自增、自减运算符(++、- -):放在操作数前,先运算再赋值;放在操作数之后,先赋值再运算。
2.关系运算符(==、!=、<、>、<=、>=):结果为Boolean型
3.赋值运算符(=)
4.逻辑运算符(&(与)、|(或)、!(非)、&&(与)、||(或))
5.位运算符:
m<<n:左移(m2en)
m>>n:右移(m2e-n)
m>>>n:无符号右移:正数时与右移一致
m&n:与运算
m|n:或运算
m^n:异或运算
6.三目运算符(m>n?m:n;)