Java是强类型的语言,学习Java,首先要学习这门程序设计语言的基础概念在程序中的实现方式.
一、数据类型:
在Java中一共有八种基础数据类型,四种整型,两种浮点型,一种表示Unicode编码的字符char类型,还有一种是表示真值的Boolean类型
- 1、整型
类型 存储需求 范围 byte 1字节 -128~127(-2的7次方到2的7次方-1) short 2字节 -32768~32767(-2的15次方到2的15次方-1) int 4字节 -2147483648~2147483647(-2的31次方到2的31次方-1) long 8字节 -9223372036854774808~9223372036854774807(-2的63次方到2的63次方-1) - 2、浮点类型
类型 存储需求 范围 float 4字节 3.402823e+38 ~ 1.401298e-45(e+38表示是乘以10的38次方,同样,e-45表示乘以10的负45次方) double 8字节 1.797693e+308~ 4.9000000e-324
double类型表示的数值精度是float类型表示数值精度的两倍,double也称为双精度数值,在实际应用中,大多数情况都是使用double,float可以在存储单精度的时候使用.
- 3、char类型
char类型的值要用单引号括起来,在Java中,char类型描述了UTF-16编码中的一个代码单元,在实际开发中,除非需要处理UTF-16代码单元,否则不建议在程序中使用char类型,建议使用字符串类型 - 4、boolean类型
boolean类型只有两个值:true和false,用来表示真和假,作为逻辑判断,整型和布尔不能互相转换
数据类型的级别从高到低为:byte,short,char(三个平级) -> int ->float -> long -> double
类型之间的转换:从低级别到高级别由系统自动转换,把高级别赋值给低级别的变量时,强制转换
每个基本数据类型都有相应的包装类型,int -> Integer ,double-> Double,float -> Float,short-> Short, long -> Long,boolean -> Boolean,char -> Character,byte -> Byte.基本数据类型和他们各自的包装类之间会有拆箱和装箱的操作,把int类型变量转换为Integer类型叫做装箱,反之则为拆箱.装箱操作都为valueOf()方法,而拆箱基本都是基本数据类型加上Value作为拆箱方法,例如intValue,longValue等等.
二、变量和常量:
- 1、变量:
变量是内存中开辟的一块存储区域,用于记录和存储不断变化的数据的值,每个变量都有自己的类型,变量类型位于变量名称之前,变量在使用前必须用赋值语句进行显示的初始化.- 空间开辟构成要素: 变量名称,变量类型,变量第一次的初始化值
- 作用: 方便运算
- 特点: 变量空间可以重复使用
- 作用域: 从变量的定义的位置开始,到变量所在的大括号结束
- 2、常量:
在Java中,常用final关键字表示常量,常量也是一块存储区域,在定义常量时会进行一次赋值,之后一直到常量的生命周期结束,该常量的值都不会被改变及被第二次赋值,也就是常量只能赋值一次,习惯上,常量为全大写.
三、运算符:
- 1、算数运算符:
+,-,*,/表示加减乘除,当参与/运算的两个数都是整数时表示整数除法,否则表示浮点除法.求余操作用%,例如15%2等于1,当整数被0除时将会产生一个异常,浮点数被0除时则会得到无穷大或者NaN结果. - 2、结合赋值运算符:
例如x+=2 就等于 x = x+2,一般要把运算符放到=号左边,%= ,*= - 3、自增自减运算符:
自增和自减运算符有两种形式,一种是"前缀"式,一种是"后缀"式,n++,n--,++n,--n.这两种的写法的区别就在于n++的方式是变量先进行计算再进行自增,++n的方式则是变量先进行自增再计算
- 4、关系和boolean运算符:
boolean运算符的结果只有两种,要么是false,要么是true.如:5==7 结果为false,还可以用!=检测不相等,3!=9结果为true,
Java中>,<,>=,<=大于,小于,大于等于,小于等于以及!来表示的逻辑非运算符.
&& , || ,|,&,^- &只有两边为true结果才为true,否则为false
- |只要两边都为false结果是false,否则为true
- ^:异或:两边结果一样,就为false,两边结果不一样,就为true
- &&和&的区别: &表示无论左边结果是什么,右边都参与运算,&&短路与,如果左边为false,那么右边不参与运算
- | 和|| 区别: |两边都参与运算,||短路或,左边为true,右边不参与运算
- 5、位运算符:
<< , >> , >>>
<<,>>运算符将位模式右移或者左移,>>>运算符会用0填充高位
四、字符串:
在实际开发中,几乎没有一个项目不使用String字符串,String字符串用双引号" "进行定义,也可以使用+号对两个字符串进行连接.
String之所以可以存储字符串主要原因是其中定义了一个数组,字符串中每个字符都是保存在数组中.在jdk1.9之前String保存的是字符数组,从jdk1.9开始,String保存的是字节数组.
1.9前源码:
private final char value[];
1.9开始源码:
private final byte[] value;
- 1、字符串比较:
示例:
String str = "abc";
String str1 = new String("abc");
System.out.println(str == str1);
运行结果:false
实际上两个相等的值比较出来却是false,原因就在于==,==比较的是两个数值是否相等,而对于两个对象则比较的是两个对象的内存地址是否相等,很显然,str和str1的内存地址是不相等.我们想要的是内容相等就返回true,在这里就需要用equals,equals比较的是两个对象的内容是否相等.把上面程序==改为equals.
String str = "abc";
String str1 = new String("abc");
System.out.println(str.equals(str1));
运行结果:true
- 2、字符串常量:
字符串常量是String类的匿名对象.任何用双引号定义的字符串常量实际上都是String类的匿名对象.在字符串的比较中需要注意一个问题,用户输入的字符串要放在equals后面.也就是字符串常量要放在前面,示例:
运行结果:java.lang.NullPointerExceptionString str = null; System.out.println(str.equals("abc"));
在输入的数据为null时,程序会抛空指针异常.下面换一种写法,
运行结果:falseString str = null; System.out.println("abc".equals(str));
两种方式只是位置不同,结果为什么会不同,其原因就在于,equals方法中提供了一个可以规避null的判断,所以把字符串常量写在前面的时候永远都不会出现空指针,因为字符串常量是一个匿名对象,匿名对象一定是开辟好堆内存空间的对象. - 3、字符串实例化的方式:
- 直接赋值给String对象
- 利用new关键字(构造方法实例化)
//直接赋值
String str = "aaa";
//new关键字赋值
String str1 = new String("aaa");
区别:
第一种实例化是直接在堆内存中开辟一块内存存放aaa,在上面已经说明,字符串常量是String的匿名对象,所以str对象则在栈内存中指向这块堆内存.只会产生一个实例化对象,会自动保存到对象池,可以实现字符串对象的重用.
第二种方式是先在堆内存中开辟内存存放aaa,在new的过程中在不同的堆内存地址开辟空间并存放aaa,在栈内存中的str1指向的是后面开辟的堆内存空间,产生两个实例化对象,不会自动保存到对象池,不可以重用.
//直接赋值
String str = "aaa";
//new关键字赋值
String str1 = new String("aaa");
//结果为false
System.out.println(str == str1);
所以,str == str1的结果为false,==比较的是两个对象的内存地址或者是数值
接下来定义一个新的对象str2,str == str2结果为true.这里结果为true,具体的原因在直接赋值的过程中,涉及到了共享设计的概念,在jvm中有对象池,当创建对象时,会将当前对象的匿名对象入池保存,当以同种方式再次创建对象,会先从池中查找是否存在与当前对象匿名对象内容相等的对象,若已经存在,则不会开辟新的空间,而是直接指向已有的地址.所以结果为true
//直接赋值
String str = "aaa";
//new关键字赋值
String str1 = new String("aaa");
//结果为false
System.out.println(str == str1);
String str2 = "aaa";
//结果为true
System.out.println(str == str2);
使用构造方法来实例化对象不会在对象池中保存,如果想要入池可以调用intern()方法.如下:
//直接赋值
String str = "aaa";
//new关键字赋值
String str1 = new String("aaa");
//结果为false
System.out.println(str == str1);
String str2 = "aaa";
//结果为true
System.out.println(str == str2);
String str3 = new String("aaa").intern();
//结果为true
System.out.println(str == str3);
- 4、常量(对象)池:
对象池的主要目的是实现数据的共享处理,String对象池里面的内容主要是为了重用,而重用实际就是共享.常量池可以两种:
1.静态常量池:在程序(.class)加载中自动将当前程序中的字符串,普通的常量,类和方法的信息等等进行分配
2.运行时常量池:当一个程序加载之后,将class文件中的常量池载入到内存中,并保存在方法区中.
看以下案例:String str1 = "ab"; String str2 = "abc"; String str3 = str1 + "c"; //结果false System.out.println(str3 == str2); String str4 = "ab" + "c"; //结果true System.out.println(str4 == str2);
以上的结果表明,如果是常量相加,JVM会进行优化,直接编译成结果,如果是变量加常量,会new一个StringBuilder对象append,最后通过StringBuilder的toString方法生成一个新的字符串对象.所以str3与str2的地址不相同.还有一个原因就是静态常量池和运行时常量池的区别,由于str4的"ab","c"都是常量数据,所以在加载的时候会自动处理相应的连接,处理好的连接刚好在静态常量池中存在,str4直接指向的对象的地址也就和str2是同一个地址,而str3中str1是一个变量,程序在加载的时候并不确定str1的内容,因为在字符串连接的时候str1采用的是变量,变量是可以被修改的,所以它不认为最终的str3结果就是需要的结果,str3存储在运行时常量池中.
- 5、字符串的修改
字符串内容不可修改
在String类中存储的是数组,而数组最大的缺点就是长度不可变,当创建了一个字符串之后,会自动的进行数组空间的开辟,开辟内容的长度是固定的. - 6、String常用方法:
- boolean equals(Object anObject) 字符串比较,相等返回true
- boolean equalsIgnoreCase(String anotherString) 字符串忽略大小写比较,相等返回true
- int length() 返回字符串长度
- String replace(char oldChar, char newChar) 返回一个新的字符串,新值替代旧值
- String substring(int beginIndex, int endIndex)
- String substring(int beginIndex) 返回新的字符串,开始下标和结束下标或者开始下标
等等......
上篇到这里结束,若有错误和补充欢迎指出
网友评论