java基础学习笔记
- java基础
- 基本数据类型转换
- 自动类型转换
- 细节
- 强制类型转换
- 基本数据类型和String转换
- 算术运算符
- 逻辑运算符
- 标识符命名规范
- Switch分支结构细节
- break 和continue标签
- 数组基础
- 方法传参机制
- 方法重载
- 可变参数
- ==作用域==
- 作用域细节
- ==**属性细节**==
- 构造器/构造方法
- 对象创建流程分析
- idea快捷键
- 包
- 访问修饰符
- 面向对象
- 封装
- 继承
- super 和 this
- super
- this
- 方法重写/覆盖(override)
- 重载(overload)和重写(override)比较
- 多态
- instanceof比较操作符
- ==java动态绑定机制==
- 多态参数
- Object 类
- equals 和 ==
- hashcode()
- toString()
- finalize()
java基础
基本数据类型转换
自动类型转换
- 介绍
java程序进行赋值和运算时,精度小的数据类型自动转换为精度大的数据类型 - 数据类型按照精度(容量)大小进行排序
注意:byte\short 和char不能相互转换!!!!
char < int < long < float < double
byte < short < int < long < float < double
int a = 10;
double b = a + 1.1; // 1.1默认是double类型,a转型为double类型再与1.1相加
float c = a + 1.1f; // 1.1f表示是单精度浮点类型
float d = a + 1.1; // 报错
float e = (float) (a + 1.1); //强制类型转换,相当于double类型结果强制类型转换为float
细节
- byte、short、char三者可以计算,三个类型不管是单独运算还是混合运算,计算时都首先转换为int
- boolean 不参与类型的自动转换
- 自动提升原则:表达式结果的类型自动转换为操作数中最大的类型
强制类型转换
- 强制符号只对于最近的操作数有效,往往使用小括号提升优先级
- char可以int型的常量值,但是不能表示变量值
基本数据类型和String转换
- 基本类型 -->String
int a = 10;
String s = a + "";
- String --> 基本数据类型
String s1 = "11";
int num = Integer.parseInt(s1);
- String -->char
String s = "123";
char ch = s.charAt(0)
// ch = '1'
//ch获得字符串“123”中的‘1’
算术运算符
- %取模运算符
关于%的本质,a % b = a - a / b * b
-10 / 3 <=> -10 - (-10)/3*3
<=> -10 + 10 / 3 * 3
<=> -10 + 3 * 3
= -1
10 / -3 <=> 10 - 10 / (-3) * (-3)
<=> 10 - 10 / 3 * 3
<=> 10 - 3*3
= 1
逻辑运算符
- && 短路与 和 &逻辑与
a = false , a && b直接得出 false,不判断第二个条件,效率高
a = false, a & b,还要判断 b 是否为 false
- || 短路或 和 | 逻辑或
a = true , a || b直接得出 true,不判断第二个条件,效率高
a = true, a b,还要判断 b 是否为 true
标识符命名规范
- 包名
多单词组成时所有字母小写:aaa.bbb.ccc - 类名、接口名
多单词组成时所有单词首字母大写 - 变量名、方法名
多单词此组成时,第一个单词首字母小写,第二个单词开始时首字母大写,采用驼峰命名法 - 常量
所有字母大写,多单词时用下划线连接
Switch分支结构细节
- 表达式数据类型,应该和case后的类型一致, 或者是可以自动转换相互比较的类型。比如输入char, 而常量是int
char a = 's';//不报错
String a = 's';//报错
switch(a){
case 'a':
case 's':
case 12:
}
- switch(表达式)中表达式的返回值必须是**byte, short, int, char, enum**
break 和continue标签
- 标签的基本使用,实际开发中尽量不使用
label1:
for(int i = 0;i < 10;i++){
label2:
for( int j = 0;j < 10;j++){
if(j == 2)
break label1;//直接跳转到label处执行
}
}
数组基础
数组定义后,如果没有赋值,有默认值
int 0, short 0, byte 0, long 0, float 0, double 0.0, char \u0000, boolean false, String null
方法传参机制
- 变量存储
- 基础类型变量:java中8种基础数据类型,基础数据类型的数据存储在栈中,即是栈中分配内存空间所包含的值,其值就是数据本身,值类型的数据具有较快的存取速度。
- 引用类型变量: 除了基础数据外,其余都是引用类型,包括类、数组等。引用类型数据的具体对象存储在堆中,而栈中存放的是该对象的内存地址,。当引用类型没有赋值时,其引用为null,表示不指向任何对象。
方法重载
- 方法名:必须相同
- 形参列表:必须不同
形参类型、个数、顺序至少有一样不同,参数名无要求。 - 返回类型: 无要求。
可变参数
- 基本概念
java 允许将同一个类中多个同名同功能但参数个数不同的方法封装成一个方法,就可以通过可变参数实现。
- 基本语法
- 访问修饰符 返回类型 方法名(数据类型…形参名){}
public class VarParameter{
// 计算2个数的和,3个数的和,4个、5个...
//1. int...表示接收的是可变参数,类型是int,数量为多个
//2.使用可变参数时可以当作数组来使用,即nums可以作为数组来使用
//
public int sum(int ... nums){
// nums可以当作数组使用数组
}
- 可变参数的实参可以是数组
- 可变参数本质是数组
- 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
//报错
public void f(double... nums, String str){}
//正确
public void f(double d1, double... nums){}
- 一个形参列表只能出现一个可变参数
作用域
- java中主要变量就是属性(成员变量)和局部变量
- 局部变量一般指在成员方法中的变量
- java作用域的分类
- 全局变量:也就是属性,作用域为整个类体
- 局部变量:也就是除了属性之外的其它变量,作用域为定义它的代码块中。
- 全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值,不能直接使用,因为无默认值。
作用域细节
- 属性和局部变量可以重名,访问时遵循就近原则
- 属性随对象创建、销毁。在一次方法调用过程中,局部变量随代码块执行而创建,随代码块结束而销毁
- 作用域范围不同
全局变量/属性:可以被本类使用,或是其它类使用(通过对象调用)
局部变量:只能在本类中对应的方法中使用 - 修饰符不同
全局变量/属性:可加修饰符
局部变量:不可以加修饰符
属性细节
- 属性如果不赋值,有默认值,规则和数组一致,具体来说:
int 0,short 0, byte 0, long 0, float 0.0,double 0.0, char \u0000,boolean false,String null
构造器/构造方法
- 构造器无返回值
- 方法名和类名一致
- 创建对象时,系统自动调用
- 如果没有定义构造器,系统会自动给类生成一个无参构造器(也叫默认构造器),比如Person(){}
- 一旦自己定义了构造器,默认构造器就覆盖了,不能再使用默认构造器,除非显示定义一下,写上Person(){}
对象创建流程分析
class Person{
int age = 90;
String name;
Person(String n, int a){
name = n;
age = a;
}
Person p = new Person("Lin", 20);
分析
- 首先在方法区加载Person类Person.class, new的时候在堆里开辟空间,这时属性都有默认值,这里age和name先默认初始化,age=0,name=null,,然后再显式初始化,age=90,name=null,
- 初始化完毕后,由Person(“lin”,20);这条语句,将参数传进去给属性赋值,"lin"会在常量池里有一个空间保存,堆中name会指向常量池"lin"的空间,最后p指向堆中对象空间,p是一个对象引用,它是引用指向一个对象。
- 加载Person类信息(Person.class),只加载一次
- 在堆中分配空间(地址)
- 完成对象初始化
3.1 默认初始化
3.2 显式初始化
3.3 构造器初始化- 把对象在堆中的地址返回给p(p是对象名,也可以理解为对象的引用)
idea快捷键
包
- 建议使用哪个类导入哪个类
访问修饰符
- 公开级别:public,对外公开
- 受保护级别:protected,对子类和同一个包中的类公开
- 默认级别:无修饰符,向同一个包的类公开
- 私有级别:private,只有类本身可以访问,不对外公开
访问级别 | 访问修饰符 | 同类 | 同包 | 子类 | 不同包 |
公开级别 | public | Y | Y | Y | Y |
受保护级别 | protected | Y | Y | Y | N |
默认级别 | 无 | Y | Y | N | N |
私有级别 | private | Y | N | N | N |
+只有默认、public可以修饰类
面向对象
封装
定义:把属性和方法封装在一起,通过被授权的方法才能对数据操作
好处:
- 隐藏细节
- 对数据验证,保证安全合理
继承
- 代码复用
- 提高扩展性、维护性
- 子类继承所有属性和方法,非私有的属性和方法可以在子类直接访问,私有属性和方法通过父类提供公共方法访问
- 细节
- 子类必须调用父类构造器,完成父类初始化
- 创建子类时,不管子类使用哪个构造器,默认情况下总会调用父类的无参构造器(子类构造器默认调用super()),如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化。
- 如果父类有多个构造器,则在子类显示调用
- super使用时放在构造器第一行,只能在构造器中使用
- super和this不能同时使用
- Object 是所有类的基类
- 父类构造器的调用不限于直接父类,将一直往上追溯到Object类
- java 单继承
- 不能滥用继承,子类和父类必须满足is-a的关系
- 继承本质
1.截的韩顺平的讲解的图,讲的太好了
子类的创建的内存布局图
super 和 this
super
- 访问遵循就近原则
- 访问不局限于直接父类
this
- 访问构造器语法:this(参数列表);只能在构造器中使用(即只能在构造器中访问另外一个构造器,必须放在第一条语句使用)。
- this不能在类定义的外部使用,只能在类定义的方法中使用。
比较
方法重写/覆盖(override)
- 细节
- 子类的方法的参数、方法名称要和父类的参数、方法名完全一样
- 子类方法的返回类型要和父类方法返回类型一样,或者是父类返回类型的子类,比如父类返回Object,在子类可以返回String
- 子类方法不能缩小父类方法访问权限
void say(){} public void say(){}
重载(overload)和重写(override)比较
多态
- 基本介绍:方法或者对象具有多种形
- 多态前提是:两个对象间存在继承关系
- 方法的多态
重写和重载就体现多态 - 对象的多态(核心)
2.1 一个对象的编译类型和允许类型可以不一致。
2.2 等号左边是编译类型,等号右边是运行类型
2.3 运行类型可以变化
2.4 编译类型在定义对象时就确定了,不能变
// animal编译类型是Animal, 运行类型是Dog
Animal animal = new Dog();
// animal 编译类型是Animal,运行类型变成了Cat
animal = new Cat();
- 向上转型
- 本质:父类的引用指向了子类的对象
- 语法:父类类型 引用名 = new 子类类型()
- 特点: 编译类型看左边,运行类型看右边
可以调用父类的所有成员(遵守访问权限)
不能调用子类特有成员
最终运行效果看子类的具体实现
- 向下转型
- 语法 子类类型 引用名 = (子类对象)父类引用
- 只能强转父类的引用,不能强转父类对象
- 要求父类的引用必须指向的是当前目标类型的对象
- 当向下转型后,可以调用子类类型的所有成员
- 属性的值没有重写之说,属性值看编译类型
class Base{
int count = 10;// 属性
}
class Son extends Base{//子类
int count = 20; //属性
}
public class T{
public static void main(String[] args){
Base base = new Son();
System.out.println(base.count) // 结果是10
Son son = new Son();
System.out.println(son.count) // 结果是20
}
}
instanceof比较操作符
- 用于判断对象的运行类型是否为某个类型或某个类型的子类型
java动态绑定机制
- 当调用对象方法时,该方法会与该对象的内存地址/ 运行类型绑定
- 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
多态参数
方法定义的形参为父类类型,实参类型允许为子类类型
Object 类
equals 和 ==
- **== **
- == :既可以判断基本类型,又可以判断引用类型
- == : 如果判断基本类型,判断值是否相等,用于判断基本数据类型
- == :如果判断引用类型,判断地址是否相等,即判断是否是同一个对象
- equals
- equals: 是Object类中的方法,只能判断引用类型
- 默认判断的是地址是否相等,也就是判断是不是同一个对象,子类往往重写该方法,用于判断内容是否相等。
hashcode()
- 提高具有哈希结构的容器的效率
- 两个引用,如果指向同一个对象,则哈希值一定一样
- 两个引用,如果指向不同对象,则哈希值不一样(小概率也可能一样,冲突了)
- 哈希值主要根据地址号来的,不能完全将哈希值等价于地址
- 在集合中,如果需要,重写
toString()
- 默认返回: 全类名+@+哈希值的十六进制
全类名=包名+类名 - 重写该方法,打印或者拼接对象时,都会调用该对象的toString形式
- 直接输出一个对象,toString方法会默认调用
finalize()
- 当对象被回收时,系统自动调用该对象的finalize方法,可重写该方法做一些释放资源的操作(比如释放资源、数据据库连接等),如果不重写,就会调用Object类的finalize方法,即默认处理。
- 什么时候回收:某个对象没有引用时,jvm就认为对象是一个垃圾,就用垃圾回收机制销毁该对象,在销毁该对象前,会先调用finalize方法。
- 垃圾回收机制的调用,由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制。