Java基础语法,常用知识复习

1.开发环境搭建

1.1JDK、JRE、JVM、的关系

JDK = JRE + 开发工具集(例如javac编译工具集等)
JRE = JVM + Java SE 标准类库

2.基本语法

2.1.java关键字的使用


2.2保留字

goto const 

2.3变量

2.3.1变量的分类
按数据类型分类

按声明的位置分类
1. 整型:byte(1字节=8bit) \ short(2字节) \ int(4字节) \ long(8字节)
  ① byte范围:-128 ~ 127
  ② 声明long型变量,必须以"l"或"L"结尾
  ③ 通常,定义整型变量时,使用int型。
④整型的常量,默认类型是:int型
2. 浮点型:float(4字节) \ double(8字节)
  ① 浮点型,表示带小数点的数值
  ② float表示数值的范围比long还大
  ③ 定义float类型变量时,变量要以"f"或"F"结尾
  ④ 通常,定义浮点型变量时,使用double型。
  ⑤ 浮点型的常量,默认类型为:double
3. 字符型:char (1字符=2字节)
  ① 定义char型变量,通常使用一对'',内部只能写一个字符
  ② 表示方式:1.声明一个字符 2.转义字符 3.直接使用 Unicode 值来表示字符型常量
4.布尔型:boolean
  ① 只能取两个值之一:true 、 false
  ② 常常在条件判断、循环结构中使用

2.3.2基本数据类型变量间运算规则
1.自动类型转换(只涉及7种基本数据类型)
结论:当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。
byte 、char 、short --> int --> long --> float --> double 
特别的:当byte、char、short三种类型的变量做运算时,结果为int型
说明:此时的容量大小指的是,表示数的范围的大和小。比如:float容量要大于long的容量
char a = 'a';
char b = 'b';
//char c = a + b;编译错误
int c = a + b;
2.强制类型转换(只涉及7种基本数据类型):自动类型提升运算的逆运算。
需要使用强转符:()
注意点:强制类型转换,可能导致精度损失。
3.String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+

2.4进制(个人觉得需要掌握)

二进制(binary)0,1  满2进一 以0b或0B开头
十进制(decimal)0-9  满10进一
八进制(octal)0-7   满8进一 以数字0开头表示
十六进制(hex)0-9 及A-F  满16进一  以0x 或0X开头表示 此处A-F不区分大小写
1.二进制的说明
1.1 计算机底层的存储方式:所有数字在计算机底层都以二进制形式存在。
1.2 二进制数据的存储方式:所有的数值,不管正负,底层都以补码的方式存储。
1.3 原码、反码、补码的说明:
正数:原码,反码,补码相同
负数:
  原码:正数的源码的符号位取反
  反码:符号位不变,其余按位取反
  补码:反码+1
1.4进制转换
十进制 -> 二进制  除2取余的逆
二进制转八进制  三位合成一位
二进制转十六进制  四位合成一位

2.5运算符

1.算术运算符: + - + - * / % (前)++ (后)++ (前)-- (后)-- + 
short s1 = 10;
s1 = s1 + 2;//编译失败
s1 += 2;//不会改变变量本身数据类型
s1 ++;//不会改变变量本身数据类型
2.赋值运算符:=  +=  -=  *=  /=  %=
3.比较运算符(关系运算符): == != >  <  >=  <=  instanceof
4.逻辑运算符:& &&  |  || !  ^
^ 逻辑异或  true ^ false == true  false ^ false == false  true ^ true == false
5.位运算符:<<  >> >>> &  |  ^  ~
【面试题】 你能否写出最高效的2 * 8的实现方式? 
答案:2 << 3  或  8 << 1
【特别说明的】
1. 位运算符操作的都是整型的数据
2. << :在一定范围内,每向左移1位,相当于 * 2  (补0)
   >> :在一定范围内,每向右移1位,相当于 / 2  (正数补0负数补1)

3.>>> 无符号右移,无符号始终补0

6.三元运算符:(条件表达式)? 表达式1 : 表达式2
//交换两个变量的值。
//方式1
int a = 1;
int b = 3;
a = a + b;
b = a - b;
a = a - b;
//方式2
a = a ^ b;// 00000001 ^ 00000011 = 00000010
b = a ^ b;// 00000010 ^ 00000011 = 00000001
a = a ^ b;// 00000010 ^ 00000001 = 00000011

3.数组

1.数组是序排列的
2.数组属于引用数据类型的变量。数组的元素,既可以是基本数据类型,也可以是引用数据类型
3.创建数组对象会在内存中开辟一整块连续的空间
4.数组的长度一旦确定,就不能修改。

image
image

数组的算法

4.面向对象(封装、继承、多态)

4.1属性

1.相同点:
  定义变量的格式:数据类型  变量名 = 变量值
  先声明,后使用
  变量都其对应的作用域.
2.不同点:
 在类中声明的位置的不同
 属性:直接定义在类的一对{}内
 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量
3.默认初始化值的情况:
属性:类的属性,根据其类型,都默认初始化值。
	整型(byte、short、int、long:0)
	浮点型(float、double:0.0)
	字符型(char:0  (或'\u0000'))
	布尔型(boolean:false)
	引用数据类型(类、数组、接口:null)
局部变量:没默认初始化值。
	意味着,我们在调用局部变量之前,一定要显式赋值。
	特别地:形参在调用时,我们赋值即可。
4.在内存中加载的位置:
属性:加载到堆空间中   (非static)
局部变量:加载到栈空间

4.2方法(重写、重载)

1.方法的重载的概念
定义:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
总结:"两同一不同":
	同一个类、相同方法名
	参数列表不同:参数个数不同,参数类型不同,参数类型的顺序不同
2.方法的重写
①yi什么是方法的重写(override 或 overwrite)?
子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作.
②应用:
重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。
③重写的规则:
4.重写的规则:
方法的声明: 权限修饰符  返回值类型  方法名(形参列表) throws 异常的类型{
   //方法体
}
约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
 >特殊情况:子类不能重写父类中声明为private权限的方法
③ 返回值类型:
>父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
>父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
>父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理时候讲)
**********************************************************************
子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写,要么都声明为static的(不是重写)。
一个为static,另一个为非static的话,编译会不通过。
3.可变个数和形参
public void show(String ... strs){}
public void show(String[] strs){}
这个两个方法不能同时存在
可变个数形参在方法的形参中,必须声明在末尾
可变个数形参在方法的形参中,最多只能声明一个可变形参。
4.值传递相关面试题
main(){
	Hello hello = new Hello();
	say(hello);
	sout(hello);//0x2345
}
say(Hello hello){
	hello = null;
	sout(hello);//null
}
5.递归

4.3封装

image

1.为什么要引入封装性?
我们程序设计追求“高内聚,低耦合”。
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
低耦合 :仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
2.封装性思想具体的代码体现:
体现一:将类的属性xxx私化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值
体现二:不对外暴露的私有的方法
体现三:单例模式(将构造器私有化)
体现四:如果不希望类在包外被调用,可以将类设置为缺省的。

4.4继承

1.为什么要有类的继承性?(继承性的好处)class A extends B{}
 * ① 减少了代码的冗余,提高了代码的复用性
 * ② 便于功能的扩展
 * ③ 为之后多态性的使用,提供了前提
2.子类继承父类以后有哪些不同?
    一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法
    特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私的结构。只因为封装性的影响,使得子类不能直接调用父类的结构而已。
    子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
3.Java中继承性的说明
    一个类可以被多个子类继承。
    Java中类的单继承性:一个类只能有一个父类
    子父类是相对的概念。
    子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
    子类继承父类以后,就获取了直接父类以及所间接父类中声明的属性和方法
4.java.lang.Object类的理解
    如果我们没显式的声明一个类的父类的话,则此类继承于java.lang.Object类
    所的java类(除java.lang.Object类之外都直接或间接的继承于java.lang.Object类
    意味着,所的java类具有java.lang.Object类声明的功能。

4.5多态

1.多态性的理解:可以理解为一个事物的多种形态。
2.何为多态性:
对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
举例:
Person p = new Man();
Object obj = new Date();
3.多态性的使用:虚拟方法调用
> 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
> 总结:编译,看左边;运行,看右边。
4.多态性的使用前提:
① 类的继承关系  ② 方法的重写
5.多态性的应用举例:
举例:
	public void func(Animal animal){//Animal animal = new Dog();
		animal.eat();
		animal.shout();
	}
6.多态性使用的注意点:
对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
public static void main(String[] args) {
	Animal animal = new Dog();
	System.out.println(animal.name);//动物
	System.out.println(animal.getName());//狗
}
class Animal{
	String name = "动物";
	int age;
	public String getName(){
		return this.name;
	}
}
class Dog extends Animal{
	String name = "狗";
	int age = 12;
	public String getName(){
		return this.name;
	}
}
************************************************************
7.关于向上转型与向下转型:
7.1 向上转型:多态
7.2 向下转型:
7.2.1 为什么使用向下转型:
有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。
子类特有的属性和方法不能调用。如何才能调用子类特的属性和方法?使用向下转型。
7.2.2 如何实现向下转型:
使用强制类型转换符:()
7.2.3 使用时的注意点:
① 使用强转时,可能出现ClassCastException的异常。
② 为了避免在向下转型时出现ClassCastException的异常,我们在向下转型之前,先进行instanceof的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。
7.2.4 instanceof的使用:
① a instanceof A:判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
② 如果 a instanceof A返回true,则 a instanceof B也返回true.其中,类B是类A的父类。
③ 要求a所属的类与类A必须是子类和父类的关系,否则编译错误。

4.6关键字

4.6.1 this
1.可以调用的结构:属性、方法;构造器
2.this调用属性、方法:
this可以理解为:当前对象或当前正在创建的对象
    在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法。但是,
通常情况下,我们都择省略"this."。特殊情况下,如果方法的形参和类的属性同名时,我们必须显式
的使用"this.变量"的方式,表明此变量是属性,而非形参。
     在类的构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法。
但是,通常情况下,我们都择省略"this."。特殊情况下,如果构造器的形参和类的属性同名时,我们必须显式的
使用"this.变量"的方式,表明此变量是属性,而非形参。
3.this调用构造器:
① 我们在类的构造器中,可以显式的使用"this(形参列表)"方式,调用本类中指定的其他构造器
② 构造器中不能通过"this(形参列表)"方式调用自己
③ 如果一个类中有n个构造器,则最多有 n - 1构造器中使用了"this(形参列表)"
④ 规定:"this(形参列表)"必须声明在当前构造器的首行
⑤ 构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器
4.6.1 super
1.super 关键字可以理解为:父类的
2.可以用来调用的结构:属性、方法、构造器
3.super调用属性、方法:
    我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用父类中声明的属性或方法。
但是,通常情况下,我们习惯省略"super."
    特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,
表明调用的是父类中声明的属性。
    特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的使用"super.方法"的方式,
表明调用的是父类中被重写的方法。
4.super调用构造器:
    我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
    "super(形参列表)"的使用,必须声明在子类构造器的首行!
    我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二一,不能同时出现
    在构造器的首行,没显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
    在类的多个构造器中,至少一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
4.6.2 static
1.可以用来修饰的结构:主要用来修饰类的内部结构
    属性、方法、代码块、内部类
2.static修饰属性:静态变量(或类变量)
    2.1 属性,是否使用static修饰,又分为:静态属性  vs 非静态属性(实例变量)
实例变量:我们创建了类的多个对象,每个对象都独立的拥一套类中的非静态属性。当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的属性值的修改。
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。
    2.2 static修饰属性的其他说明:
     ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
     ② 静态变量的加载要早于对象的创建。
     ③ 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
     ④          类变量  实例变量(是否可以调用)
      类          yes     no
      对象(引用)   yes     yes
2.3 静态属性举例:System.out; Math.PI;

4.7补充