Java语法学习记录
基本数据类型
byte 一个字节(服务器端编码的时候按照byte编码,整数变量)
short 两个字节
char 两个字节(因此可以存储汉字,而c/c++的char只有一个字节无法单独存储汉字,但可以用char数组存储汉字)
int 四个字节
float 四个字节,有效数字位数是8位
long 八个字节
double 八个字节,有效数字位数是16位
985211(默认是int型常量)
985.211(默认是double型常量)=》float=985.211会报错需要类型强转为float类型
985211L(long型常量)
985211F(float型常量)
算数混合运算精度
精度排序:
byte<short<char<int<long<float<double
如果表达式中有双精度浮点数(double型数据),则按双精度进行运算。
例如:985.211/123结果就是double类型数据。
同样如果是单精度浮点数(float类数据),则按单精度进行运算。
以此类推long和int
但是注意:
如果表达式的最高精度低于int型整数,则按int精度计算。
因为不加后缀的整数都默认是int型
例如:(byte)10+'a’和5/2的结果分别为107和2,都是int型数据。
成员变量,局部变量
成员变量:
类体中声明的变量
有效范围:有效性和它在类体中书写的先后位置无关,因为都是先new出来,方法才能使用,类似数组定义运行,所以存在初始值。
成员变量有初始值。
注意问题:
类体中的内容由两部分组成,一部分是变量的声明;另一部分是方法的定义。
对于成员变量的操作只能放在方法中,方法使用各种语句对成员变量和方法体中声明的局部变量进行操作。
声明成员变量时可以赋初值
class A{
int a=666;
int b=a;
}
不可以进行赋值操作
class A{
int a;
a=666;
}
局部变量:
方法体中声明的变量
有效范围:只在方法内有效,而且从声明它的位置之后开始有效。
局部变量没有初始值(局部静态变量也没有)
if(条件表达式)-else
条件表达式结果都得为boolean类型
if(条件表达式)括号中结果必须为boolean类型,不能使用0或者null作为false使用
switch(byte,short,int,char)
相比较if-else,switch-case只判断一次就跳转,性能更强大。
但是switch的表达式只能是byte,short,int,char类型。
switch(byte,short,int,char){
case byte,short,int,char:
******;
break;
case byte,short,int,char:
******;
break;
default:
****** ;
break;
}
while(条件表达式)循环和for(表达式:条件表达式:表达式)循环
条件表达式结果必须为boolean类型
数组操作
java的数组名之间是可以相互赋值的,但是C/C++不可以。
C/C++数组名是一个地址常量
C/C++语言在最终的汇编结果中,数组名只是一个标号,对应一个地址,在程序中使用数组就是要替换成这个起始地址,因此作为标号本身是不可以修改的,也不是一个变量。
用数组名进行计算就是用数组起始地址计算,但不可以给数组名重新赋值
int a[]=new int[666];
int b[]=new int[888];
b=a;//java是可以的,可能是因为都是动态new出来的动态地址,并且有垃圾收集机制所以没有问题。
定义基本类型数组
同:
可以进行数组的初始化构建数组。
int num[]={985,211};
java的String数组初始化
String s[]=new String[]{"zero","one","two","three","four","five","six","seven","eight","nine","ten"};
c++的String数组初始化
string s[]={"zero","one","two","three","four","five","six","seven","eight","nine","ten"};
异:
c/c++版本
数组元素无初始值。
int num[666];
java版本
-
需要进行new操作指定元素个数,不允许声明时直接指定个数。
-
无论二维数组以任何形式声明(int a[][],int []a[],int [][]a),数量都是new时指定的。
new int[666],类似于初始化的构造方法,因此java中数组元素都会有初始值。
int num[]=new int[666];
注:
new String();创建的对象并不为空,系统是分配了内存空间的,只是它没有赋值;String str=“”;str也不为空,只是赋值为空的字符串;String str=null;str为空,没有内存空间,什么也没有,不能调用它的属性,会有异常抛出
定义对象数组
//先是定义了存储对象引用的对象指针类型,初始值为null
Student stu[]=new Student[666];
//然后给每个对象元素进行引用赋值
for(int i=0;i<stu.length;i++)
stu[i]=new Student();
数组遍历
//多用于list数组,未知数组长度
//list数组不能为基本数据类型(String不是基本数据类型),因为可以直接使用基本数据类型数组,无需多此一举
for(声明循环变量:数组名字){
(list.size()-1==list.indexOf(listObject)//可以判断遍历的元素是否是最后一个元素
}
注意一定要是在for循环条件中声明循环变量。
int num[]=new num[666];
错误示范:
int i=0;
for(i:num)
正确操作:
for(int i:num)
替代操作:
for(int i=0;i<num.length;i++)
类与对象的注意事项
Java应用程序中含有一个主类,即含有main方法的类,Java应用程序加载到内存中后会从main方法开始执行。
注意:执行的main方法是选中类的main方法,运行其余类的main方法需要调用,而选中类的方法是系统自动调用的。
也可以通过注入@test方式运行测试指定的方法。
默认是先加载分配类变量,然后运行main方法。(分配好类变量,main方法才能调用)
- 如果定义了带有参数的构造函数,则默认构造函数失效
- 原来的默认函数(没有参数的默认函数)需手动定义
书写规范
- 声明类时,单词首字母大写(多个单词那就多个首字母大写)。
- 项目名,包名全部小写且若为多个单词用_连接。
- 声明变量和方法时,变量名的首字母小写,其余单词首字母大写。
class PersonInformation{
}
成员变量
int personCard;
类体中的内容由两部分组成,一部分是变量的声明;另一部分是方法的定义。
对于成员变量的操作只能放在方法中,方法使用各种语句对成员变量和方法体中声明的局部变量进行操作。
声明成员变量时可以赋初值和new等操作,只要是声明时的操作就行。
class A{
int a=666;
int b=a;
类 对象变量=new 类();
}
不可以进行赋值操作
class A{
int a;
a=666;
}
类变量(static)
当Java程序执行的时候,类的字节码文件被加载到内存中,如果该类没有创建对象,类中的实例变量不会被分配内存。但是类中的类变量,在该类被加载到内存的时候,就分配了对应的内存空间并且初始化。
类方法(static)
当类方法为main方法时才会在加载后被调用运行,其余类方法只是分配地址还需类名.或者bean.或者main中进行调用。
- 实例方法只有当创建第一个对象的时候才会被分配入口地址,所有对象都用这一个入口地址。
- 可以用类名直接调用类方法和类变量使用。
- 当全部对象不存在时,入口地址才会被取消。
- 类方法是当类被加载到内存中时就会被分配入口地址,类方法只能操作类变量和类方法内定义的局部静态变量。(程序加载到内存中时,先给类变量分配空间,然后才会给类方法分配入口地址,因为类方法需要用到类变量)
举例:
Arrays类存在sort和binarySearch等类方法且可以直接类名调用类方法Arrays.sort(),Arrays.binarySearch()。
对象
- 对象其实还是个指针,存储的是对应实体(分配给对象的变量)地址。
- 垃圾回收机制:就是将不再存在对象指向的引用(地址)调用,就对其对应实体进行内存释放。
注意:
- Object有个toString实例方法。
- Object类的 toString方法返回一个字符串,该字符串由
类名(对象是该类的一个实例)、标记符“@”和此实例化对象内存地址哈希码的无符号十六进制表示组成。
换句话说,该方法返回一个字符串,它的值等于:
getClass().getName() '@' Integer.toHexString(hashCode())
- 在Java中,所有的对象都是继承自Object,因此所有的Java对象(不管什么类型的)都具有toString方法, 但很多类都重写了Object类的toString 方法,用于返回可以表述该对象信息的字符串(例如Interge类返回整数值的字符串类型)。
所有的Java对象(各种数据类型)都可以和字符串进行连接运算,当Java对象和字符串进行连接运算的时候,系统自动调用Java对象的 toString方法的返回值 和字符串进行连接运算,即下面两行代码的结果相同:
String pstr=对象+"";
String pstr=对象.toString+"";
String toString():返回该对象(不管什么类型)的字符串表示。
当程序使用System,out.println()方法输出一个对象,或者把某个对象和字符串进行连接运算时,系统会自动调用该对象的toString方法返回该对象的字符串表示。也就是说,下面两行代码是等价的:
System.out.println(对象);
System.out.println(对象.toString());
空引用变量调用toString方法,会引起空指针异常
对象=null;
System.out.println(对象);//输出null没问题
System.out.println(对象.toString());//不行,指针异常。
this关键字
用于实例方法和构造方法,代表调用该方法的bean本身进行的操作。
常用于实例成员变量的名字和局部变量的名字相同时,成员变量前面的“this.”或者"类名."就不可省略了。
但不可以用于类方法,因为此时可能还没有实例对象bean。
static{}静态代码块与{}普通代码块之间的区别
大佬详细介绍static静态代码块和普通代码块区别
静态代码块主要是赋值初始化全局静态变量等操作,极少定义局部静态变量。
区别很简单:
静态代码块,在虚拟机加载类的时候就会加载执行,而且只执行一次; 非静态代码块,在创建对象的时候(即new一个对象的时候)执行,每次创建对象都会执行一次一个程序可以有多个静态非静态代码区域。
static{}(静态代码块)与{}(非静态代码块)的异同点
相同点 都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,
一般在代码块中对一些static变量进行赋值。.
另外static块中只能使用static修饰的属性。
程序中的static{}块只是为了加载properties文件信息,这个加载只会被加载一次。
不同点 静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。
静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new
一次就执行一次。非静态代码块可在普通方法中定义(不过作用不大);而静态代码块不行。
一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的; 需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序来调用的时候,需要使用静态方法,这种代码是被动执行的.静态代码块和静态方法的区别
两者的区别就是:静态代码块是自动执行的;
静态方法是被调用的时候才执行的.
作用:静态代码块可用来初始化一些项目最常用的变量或对象(连接数据库等);静态方法可用作不创建对象也可能需要执行的代码. 因此静态代码块先于main函数执行。
静态代码段注意事项: 静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。
静态代码块里面的变量都是局部变量,只在本块内有效。 静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。 一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。 静态代码块只能访问类的静态成员,而不允许访问实例成员。
static变量,static代码块,static方法运行顺序
当对应类加载到内存中时
static变量-》static代码块-》static方法
对于成员变量,非静态代码,实例方法也成立
成员变量-》非静态代码-》实例方法
因为代码块和方法都可能会用到static变量,所以先new变量。
而代码块需要初始化对应的static变量,方法可能会用到初始化好的static变量。
包与import
当类都在同一个包中时无需import,可以直接使用同一包下的类。
- Java.lang包是Java语言的核心类库,系统自动引入了,java.lang包中的类(例如:System类,Math类等)还有Byte,Integer,Short,Long,Float,Double,Character等封装类(下图所示)。
- 使用import引入的类时,需要注意该类方法最好设置为public类型,否则protected或者友好类型会导致方法不能使用。
- 同一包下的,无需import,所以方法可以是protected和友好
jar包是实用类的字节码(class)文件经过压缩后的文件,jar包的跨平台导入使用,也体现了java的可移植性
jar包
默认导入的java.lang包
子类与继承
- 子类只继承父类的部分变量和方法(非private),但是创建子类实例的时候,隐藏的变量也被匹配了空间,因为对象是从父类开始加载一直加载到子类。
所以子类继承的方法可以操作子类继承和隐藏的成员变量,子类新定义和重写的方法可以操作子类继承和新声明的变量但无法操作子类隐藏的变量。 - final类不可以被继承,final方法不可以被重写,final变量为常量
- abstract类可以有非abstract方法也可以有abstract方法,但是abstract方法只允许声明不允许实现,非抽象子类继承后必须实现abstract方法,所以非抽象类不允许有abstract方法。
因为含有abstract方法的类不能new对象,而非抽象类可以new。 - interface只有常量和抽象方法两部分(public,final,static),implements可以实现多个接口,且一个接口可以继承多个接口。
上转型对象
不只是abstract类允许上转型,普通类也可以。
上转型对象可以通过操作重写的方法间接操作新增的变量和新增的方法。
图示子类和上转型对象可以操作的变量和方法。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a33642027f9f1e9772c50d75cb58a2c0.png)
注意:当上转型对象(Object)转为Json序列化字符串时,Json的key键会保留子类对象的全部属性(implements Serializable)。
super关键字
super.隐藏的变量/方法。
super()调用父类的构造方法。
由于子类不继承父类的构造方法,因此,子类在其构造方法中需要使用super来调用父类的构造方法,也就是如果子类没有使用super指定调用父类哪个构造方法,就默认调用无参构造方法(super.())。
而且super必须是子类构造方法的头一条语句.因为是先加载的父类。
注意,如果父类没有无参构造方法,那么子类构造方法就要使用super进行显示声明父类拥有的构造方法了。
接口
jdk1.8后接口的相关修改;default方法
接口中只有常量(不能有变量)和抽象方法两部分。
并且所有常量都默认是public static final(允许省略)
抽象方法默认是public abstract(允许省略)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3aa34e4cfbe81033922afce6953abaaa.png#pic_center)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ac20c21b4130e7ac832e22f734dc0f61.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/eaefd685716efae38cd4ac2bdf84fdf2.png)
接口实现类
接口实现类可以实现多个接口,实现(implements)的接口方法。
重写:
方法的名字,参数个数,参数的类型和父类的方法完全相同,返回值可以不同(但是也必须为父类的子类型)。
重载
参数的个数不同。
参数个数相同,但参数列表中对应的某个参数的类型不同。
(方法返回类型和参数的名字不参与比较)
返回类型 方法名(参数类型 ,参数类型)
必须显示的用public修饰重写的方法。
因为重写不能降低访问权限,但是可以提高访问权限。
内部类与异常类
内部类
内部类就是在类中再声明一个类,但是和设计模式中的开闭原则还有单一原则等冲突,耦合性高。
内部类特性:内部类可以用static修饰,非内部类不可以是static类。
匿名类(继承式)
- 用匿名类创建对象,要直接使用父类的构造方法,所以需要继承父类。
- 匿名类可以继承父类方法也可以重写父类方法。
- 使用匿名类时,必然是在某个类中直接用匿名类创建对象,因此匿名类一定是内部类。
- 匿名类可以访问外嵌类中的成员变量和方法,匿名类的类体中不可以声明static成员变量和static方法。
假设Bank是类
new Bank(){
匿名类的类体
};
效果等同于一个继承了Bank类的子类声明一个对象。
常用实用类
泛型与集合框架
泛型类声明:
class People<E>{
}
People people=new People<Student>();
People是泛型类的名称,E是其中的泛型,也就是说,并没有指定E是何种类型的数据,它可以是任何对象或者接口,但不能是基本类型数据=》因此List<不能为基本类型数据>(如果想使用基本类型可以将对应的分装类代替E,Integer=int,会自动装箱拆箱)
堆栈:Stack<E>
散列映射:HashMap<K,V>
注意
定义变量的有效范围为包裹该变量最内层的{}。
在java中String类不可变的,创建一个String对象后不能更改它的值。所以如果需要对原字符串进行一些改动操作,就需要用StringBuilder类或者StringBuffer类,StringBuilder比StringBuffer更快一些,缺点是StringBuilder不是线程安全的,但在算法竞赛中一般我们用不到多线程。所以,主要推荐使用StringBuilder类。
JAVA语言跨平台基本原理:不将源程序(.java)直接编译成机器语言,因为这样就与平台相关了,而是将源程序编译为中间字节码文件(.class);然后再由不同平台对应型号的解释器程序(虚拟机)对字节码进行二次翻译,将字节码解释成具体平台上的机器指令,然后执行这些机器指令。
例如:jar包(class字节码文件经过压缩)的跨平台移植性。