1.关键字和标识符的辨识
标识符:
Java 中标识符是为方法、变量或其他用户定义项所定义的名称。标识符可以有一个或多个字符。(通俗的讲就是给定义类名,变量名,方法名的时候需要遵守的命名规则)
规则:
- 标识符由数字(0-9)和字母(A-Z 和 a~z)、美元符号($)、下划线(_)以及 Unicode 字符集中符号大于 0xC0 的所有符号组合构成(各符号之间没有空格)。
- 标识符第一个符号可以为字母,下划线以及美元符号(首符号不可以为数字)
- 不能使用任何 Java 关键字作为标识符,而且不能赋予标识符任何标准的方法名
- 标识符内可以包含关键字,但不能与关键字完全一样
例子:
- 合法标识符:date、$2011、_date、D_$date 、Public
- 不合法的标识符:123.com、2com、for、if 、public
关键字:
Java 的关键字对 Java 编译器有特殊的意义,它们用来表示一种数据类型,或者表示程序的结构等。
保留字是为 Java 预留的关键字,它们虽然现在没有作为关键字,但在以后的升级版本中有可能作为关键字。(常抠这几个保留字考)
Java 语言目前定义了 51 个关键字,这些关键字不能作为变量名、类名和方法名来使用。以下对这些关键字进行了分类。
- 数据类型:boolean、int、long、short、byte、float、double、char、class、interface。
- 流程控制:if、else、do、while、for、switch、case、default、break、continue、return、try、catch、finally。
- 修饰符:public、protected、private、final、void、static、strict、abstract、transient、synchronized、volatile、native。
- 动作:package、import、throw、throws、extends、implements、this、supper、instanceof、new。
- 保留字:true、false、null、goto、const。
除了一些常用的(一般不考常用的)外,需要熟记一些不太常用的关键字:
- default
- transient
- volatile
- native
- package
- strict
- instanceof
- (保留字):true、false、null、goto、const
2.Java变量的作用域
根据作用域的不同,一般将变量分为不同的类型:成员变量和局部变量。成员变量又称为静态变量和全局变量
名称 | 修饰 | 访问方式 |
---|---|---|
全局变量(实例变量) | 无static修饰 | 对象名+变量名 |
静态变量(类变量) | 用static修饰 | 类名.变量名或对象名.变量名 |
常常考static变量调用非staiic方法,即类名+全局变量/全局方法
3.Java数据类型(基本数据类型 + 引用数据类型)
常常考java基本数据类型所占字节数(经常混淆),以及各种数据类型之间的转换
基本数据类型
基本数据类型包括 boolean(布尔型)、float(单精度浮点型)、char(字符型)、byte(字节型)、short(短整型)、int(整型)、long(长整型)和 double (双精度浮点型)共 8 种
类型名称 | 关键字 | 字节数 | 包装类 |
---|---|---|---|
布尔型 | boolean | 1 字节 | Boolean |
字节型 | byte | 1 字节 | Byte |
字符型 | char | 2 字节 | Character |
短整型 | short | 2 字节 | Short |
整型 | int | 4 字节 | Integer |
长整型 | long | 8 字节 | Long |
单精度浮点型 | float | 4 字节 | Double |
双精度浮点型 | double | 8 字节 | Float |
数据类型之间的转换
原则:
- 高精度型转低精度类型时,需要强制转,相反则直接转
- 小字节数转大字节数可以直接转,反之需强转(排除double以及float)
- 强转容易精度缺失
- 包装类转相对应的基本类型,则自动解包
例子:
Double d=50.2;
double oo=d;
double e=62.2;
int s=d.intValue();
int dd=(int)e;
System.out.println(oo);//自动解包----输出 50.2
System.out.println(s);//调用包装类方式实现强转----输出50
System.out.println(dd);//直接强转---输出62
字符串与基本数据类型的转换:
字符串转基本类型
- 调用所需数据类型的包装类转换(字符串转基本类型)
String num="50";
int str=Integer.valueOf(num);
int str2=Integer.parseInt(num);
System.out.println(""+str+","+str2);//----输出 50,50
基本类型转字符串
-
String类的静态方法valueOf(参数),参数是要转化的基本数据类型(基本类型转字符串)
-
使用包装类的静态方法toString(参数),参数是要转化的基本数据类型(基本类型转字符串)
int num=50;
short num1=50;
String str=Integer.toString(num);//----输出 50
String str2=Short.toString(num1);//----输出 50
4.Java方法重写与重载
重写
刷题常考方法的重写和重载,简单概括地说,重写就是从父母继承的房子,可以改一下里面的装修,用于其他用途,比如本来用来居住的变成用来当KTV。
规则:
- 父类与子类的参数列表、返回类型必须相同
- 子类的访问修饰符必须比父类更宽松
- 父类若有异常处理时,子类重写的时候也需要异常处理
例子:
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Bird extends Animal{
public void move(){
super.move(); // 应用super类的方法---输出动物可以移动
System.out.println("鸟可以飞和走");//----输出鸟可以飞和走
}
}
public class test{
public static void main(String args[]){
Animal b = new Bird(); //
b.move(); //执行 Bird类的方法
}
}
重载
重载就是面向对象的多态特性的显现,一个构造方法通过不同的参数匹配达到不同的效果
规则:
- 重载的方法的参数列表一定不能和原来的一样,方法名一定要相同
- 可以有一样的返回类型
- 可以有一样的访问修饰符
- 可以抛出不同的异常
例子:
public class Test {
public int show(){
System.out.println("没有参数");
return 1;
}
public void show(int a){
System.out.println("有一个参数");
}
//以下两个参数类型顺序不同
public String show(int a,String s){
System.out.println("有两个参数顺序不同a");
return "returntest3";
}
public String show(String s,int a){
System.out.println("有两个参数顺序不同b");
return "returntest4";
}
public static void main(String[] args){
Test o = new Test();
System.out.println(o.show());//--输出 没有参数 再 返回1
o.show(1);//----输出 有一个参数
System.out.println(o.show(1,"test3"));//--输出 有两个参数顺序不同a 再 返回 returntest3
System.out.println(o.show("test4",1));//--输出 有两个参数顺序不同b 再 返回 returntest4
}
}
总结区别:
- 方法重写:
- 有继承关系的子类中
- 方法名相同,参数列表相同(参数顺序、个数、类型),方法返回值相同
- 访问修饰符,访问范围需要大于等于父类的访问范围
- 方法重载:
- 同一个类中
- 方法名相同,参数列表不同(参数顺序、个数、类型)
- 方法返回值、访问修饰符任意
5.代码块
经常有代码题目要求判断代码输出运行先后的问题
代码块快分为:
- 构造代码块(即无设定的时候程序初始化对象的时候默认生成一个无参的类构造方法),new多少次则生成多少次块内信息
- 静态代码块(即仅用static修饰的代码块)仅在第一次初始化该类对象的时候调用一次,且优先级优先于普通代码块和构造代码块
- 普通代码块(无任何修饰,仅仅只是一个代码块),new多少次则生成多少次块内信息
优先级:静态代码块 > 普通代码块 > 构造代码块
public class staticProgram {
public staticProgram(){
System.out.println("构造代码块执行");
}
{
System.out.println("普通代码块执行");
}
static {
System.out.println("静态构造块执行");
}
public static void main(String[] args) {
new staticProgram();
new staticProgram();
new staticProgram();
}
//静态构造块执行
//普通代码块执行
//构造代码块执行
//普通代码块执行
//构造代码块执行
//普通代码块执行
//构造代码块执行
}
6.String类对象的两种实例方法比较
经常考两个变量是否是同一对象,这就要具体分析其创建过程的数据存放及其引用方法
- 简单创建String对象:
String strA ="mldn";
String strB ="mldn";
System.out.println(strA==strB);//true
//表示这两个对象所指的内存空间是同一个地址
当创建一个String对象的时候,栈内存存进去该变量的名称,然后数值存入堆内存的字符串池(字符串池其实就是数组),当再次创建一个String对象的时候,会先查询一下该数值是否已经存在于字符串池(数组)中,如果存在则直接指向已有的数值,指向已存在的数值地址,所以返回的地址是 true
如果新创建的String对象并没有对应已存在的指向数据,则新开辟字符串池(数组)的一个空间
- new 方法创建对象:
这种创建对象的方法不会去查询字符串池中是否已存在该数值,而是直接另外开辟一个空间(不在原来的字符串池中,而是特殊另外开辟一段内存空间)存储,这种方式容易存在垃圾空间(重复数据占用内存)
此时可以调用 intern() 方法手动入池管理,数值一致的情况下内存地址一致
面试题:请解释String类两种对象实例化的区别:
- 直接赋值:只是产生一个实例对象,并且可以自动保存到对象池中,以实现该字符串实例的重用
- new 方法赋值:会产生两个实例化对象,并且不会自动入池,无法实现对象的重用,但是可以利用 intern()方法手动入池。
7.String对象常量池
- 静态常量池
程序在加载时,所有的变量都已经确定
- 运行时常量池
程序在加载的时候并不确定info是什么内容,因为在字符串拼接的时候,Info采用的是一个变量,变量的内容是可以修改的,所以他不认为最终的strB的结果就是一个所需要的最终结果
8.字符串修改分析(String不可修改)
虽然最后的str是拼接完成了,但早已不是一开始str的地址了,这种拼接方式会积累存在越来越多的垃圾空间,并且str的指向要不断变化指向,从而导致程序的性能将会非常的差
9.多态转型
刷题经常刷到考核对多态转型的阅读编程题
对象向上转型:
class Animal{
public void show(){
System.out.println("调用父类的方法");
}
}
class Human extends Animal{
public void show(){
System.out.println("调用子类的方法");
}
}
public class javademo {
public static void main(String[] args) {
//前面的Animal只是表示一种类型,没有其他意思,就是人是动物这样的解释
//而具体调用谁的方法,得看new关键字后的是哪个类
Animal animal=new Human();//向上转型
animal.show();
}
}
//-----输出: 调用子类的方法
向上转型的便利属于程序的可维护性设计,并且可以根据不同的场景设置不同的输出需要,而不采用全部都覆写的方式书写,又便于代码量的书写控制,比如 需要调用父类,把对象包裹在统一的方法内进行输出,而不用覆写的话还要覆写父类的方法,一个两个还好,要是几千几万个呢?
class Animal{
public void show(){
System.out.println("调用父类的方法");
}
}
class Human extends Animal{
public void show(){
System.out.println("调用子类人类的方法");
}
}
class Dog extends Animal{
public void show(){
System.out.println("调用子类狗类的方法");
}
}
public class javademo {
public static void main(String[] args) {
fun(new Human());
fun(new Dog());
}
public static void fun(Animal msg){
msg.show();
}
}
对象向下转型:
当子类需要使用自己的固有属性的定义的时候,需要对象的向下转型
例如 超人与普通人,超人与普通人的区别主要是他会飞,其他属性一致
class Human{
public void show(){
System.out.println("正常人");
}
}
class SuperHuan extends Human{
public void fly(){
System.out.println("我可以飞");
}
public void fire(){
System.out.println("我可以喷火");
}
}
public class javademo {
public static void main(String[] args) {
System.out.println("-----正常情况下的人-----");
Human human=new SuperHuan();//向上转型
human.show();
System.out.println("-----需要变身的时候----");
SuperHuan superHuan=(SuperHuan)human;//向下转型
superHuan.fly();
superHuan.fire();
}
}
//----输出:
// -----正常情况下的人-----
//正常人
//-----需要变身的时候----
//我可以飞
//我可以喷火
总结
向下描述的是一些公共的特征,而向下描述的是子类自己特殊的定义环境。但是需要明确的是向下转型并不是一项安全的事情。因为在进行向下转型之前一定要进行向上转型
class Human{
public void show(){
System.out.println("正常人");
}
}
class SuperHuan extends Human{
public void fly(){
System.out.println("我可以飞");
}
public void fire(){
System.out.println("我可以喷火");
}
}
public class javademo {
public static void main(String[] args) {
System.out.println("-----正常情况下的人-----");
Human human=new SuperHuan();//向上转型
human.show();
System.out.println("-----需要变身的时候----");
SuperHuan superHuan=(SuperHuan)human;//向下转型
superHuan.fly();
superHuan.fire();
Human human1=new Human();
SuperHuan superHuan1=(SuperHuan)human1;//向下转型错误例子
superHuan1.fly();
}
}
//----输出:
// -----正常情况下的人-----
//正常人
//-----需要变身的时候----
//我可以飞
//我可以喷火
//Exception in thread "main" java.lang.ClassCastException