Java基础知识点
基本数据类型值传递传递的是值,形参改变,实参不变
引用数据类型值传递传递的是地址值,形参改变,实参也变
特殊:String 在值传递时,形参改变,实参不会改变(字符串是常量,不允许改变)
== 比较
基本数据类型:比较的是基本数据类型的值是否相同
引用数据类型:比较的是引用数据类型的地址值是否相同
栈里面存的变量或者引用数据名属于实参,给方法里面传的是形参(在方法小括号里面)
形参:用于接收实际数据的变量
实参:实际参与运算的变量
计算机存储设备的最小信息单元叫“位(bit)”,我们又称之为“比特位”,通常用小写的字母b表示。而计算机最小的存储单元叫“字节(byte)”,通常用大写字母B表示,字节是由连续的8个位组成。
字符串是一个常量,一经赋值,不允许改变,字符串直接赋值(String s=“abc”)存放在字符串常量池中,(String s=new String()),new出来的东西都是存在堆内存中,每一次new都是声明一个新的变量
字符串的拼接操作本质上并不是修改字符串,(常量池里面的内容一经声明,不允许修改)拼接操作是在常量池里重新声明一个新的字符串,然后将字符串的指向修改为指向这个新声明的字符串(修改字符串的指向,并没有修改字符串的地址值字符串的地址也发生了改变),以此达到拼接字符串的目的
-
String str1 = new String(); str1 += "abc"; System.out.println(str1); //abc String str2 = str1.concat("abc"); System.out.println(str2); //abcabc String str = "ankcj"; //获取字符串的地址 Integer.toHexString(str.hashCode()) System.out.println("@" +Integer.toHexString(str.hashCode()));//@58a86c5
char 默认值’\u0000’ (空格) int 默认值 0 boolean默认值false double默认值0.0
数据类型转换
我们在做运算的时候,一般要求参与运算的数据类型必须一致。
隐式转换 byte,short,char --> int --> long --> float --> double
强制转换 目标类型 变量名 = (目标类型) (被转换的数据);
不建议强制转换,因为会有精度的损失。
一旦运算当中有不同类型的数据,那么结果将会是数据类型范围大的那种(隐式转换)
只有变量才能使用自增、自减运算符。常量不可发生改变,所以不能用
只有变量才能使用赋值运算符(=,+=,-=,*=,/=),常量不能进行赋值。
复合赋值运算符其中隐含了一个强制类型转换。(+=,-=,/=,)
逻辑运算符
& 逻辑与:有false则false。
| 逻辑或:有true则true。
^ 逻辑异或:相同为false,不同为true。
! 逻辑非:非false则true,非true则false。
&& 与(并且):全都是true,才是true;否则就是false
|| 或(或者):至少一个是true,就是true;全都是false,才是false
! 非(取反):本来是true,变成false;本来是false,变成true
注意:
- &&和||具有短路效果,左边如果已经确定结果,则右边语句不会再执行
- |和& 没有短路效果,左边代码和右边代码都会执行
switch(表达式) {case…default…}
表达式的取值:byte,short,int,char(long不可以做switch的表达式)
JDK5以后可以是枚举
JDK7以后可以是String
注意:
- 在switch语句中,如果case的后面不写break,将出现穿透现象,也就是不会在判断下一个case的值,直接向后运行,直到遇到break,或者整体switch结束。 break表示中断,结束的意思,可以结束switch语句。
- default语句表示所有情况都不匹配的时候,就执行该处的内容,和if语句的else相似。
for循环语句和while循环语句的小区别:
控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继续使用,如果你想继续使用,就用while,否则推荐使用for。原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。
循环的使用推荐:for – while – do…while
随机数
Random类 需要导包、创建对象、使用
Math.random() 无需导包,直接使用,产生的是0~1 [0,1) 之间的随机小数
JVM内存划分
-
栈 存储局部变量
-
堆 存储new出来的东西
-
方法区 (面向对象进阶讲)
-
本地方法区 (和系统相关)
-
寄存器 (给CPU使用)
类的五大成分
1.成员变量
2.构造器
3.成员方法
4.代码块
5.内部类
四大修饰符
-
public:可以修饰类、属性、方法
-
protected:可以修饰属性、方法
-
default:可以修饰类、属性、方法
-
private:可以修饰属性、方法
-
注意:1.如果public修饰外部类,那么外部类名要和文件名保持一致
2.protected的受保护的方法,在同包下、本类中可以直接调用;但是在不同包的子类中,创建父类对象访问不到父类的保护方法,只能用子类对象来访问受保护方法,且子类对象要重写保护方法
public 公开的 | protected 受保护的 | default 默认的 | private 私有的 | |
---|---|---|---|---|
本类中 | OK | OK | OK | OK |
同包下 | OK | OK | OK | |
不同包下的子类 | OK | OK | ||
不同包下的其他类 | OK |
方法的重载 Overload
-
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可
-
与返回值类型无关,只有参数个数,参数类型,参数顺序有关
-
要求:
1.发生在同一个类中
2.方法名相同
3.参数列表不同(参数个数不同,参数类型不同,参数顺序不同)
4.与返回值无关
-
int ----> String
-
String---->int
//int ---> String
int a = 10;
String s = ""+a; //10
//int ---> String
String str = Integer.toString(100);
System.out.println(str); //100
//String ---> int 当String内容全是十进制数字时才能转化
String s3 = "30";
Integer c = Integer.valueOf(s3);
System.out.println("c = " + c); //30
int d = Integer.parseInt(s3); //30
int max = Integer.MAX_VALUE; //2147483647
int min = Integer.MIN_VALUE; //-2147483648
方法重写 @Overside
-
发生在继承关系中 子类重写父类的方法
-
方法名相同
-
参数列表相同
-
返回值类型:如果是基本数据类型要一致;若是引用数据类型,子类 <= 父类
-
访问权限:子类 >= 父类
-
抛出异常:子类 <= 父类 ,子类抛出异常比父类要小
方法重写的特殊点:
1.构造方法不会被重写
2.私有方法不会被重写
3.静态方法不会被重写
局部变量,成员变量,成员方法
- 成员变量 就是事物的属性 ,可以不初始化,会提供默认值 位置:类中,方法外
- 成员方法 就是事物的行为 位置:类中
区别 | |
---|---|
局部变量 | 栈内存中,在使用前要赋初始值,在方法内声明或者作为方法的形参 随着方法的调用而存在,随着方法的调用结束而结束 |
成员变量 | 堆内存中,在类中方法外声明,可不赋初始值,会提供默认值 随着对象的存在而存在,随着对象的消失而消失 |
成员方法 | 描述事物的行为,在类中定义 |
构造方法
- 方法名与类名一致
- 没有返回值,更没有void
- 意义:实例化对象
- 若类中未提供构造方法,将默认提供一个无参的构造方法;
- 当类中提供了有参的构造方法之后,将不再提供默认无参构造方法
- 构造方法也可以进行方法重载
什么是封装
- 面向对象的三大特性之一
- 将不需要对外提供的内容都隐藏(private)起来(隐藏其内部结构)
- 把属性隐藏,提供公共方法对其访问
- 属性私有化,提供对应公开的getXxx()/setXxx()方法
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性,实现代码的组件化设计
- this 代表当前正在创建的对象,当前正在使用的对象
什么是继承 extends
- is-a 类与类之间的关系 extends关键字
- 面向对象的三大特性之一,设计层面概念
- java支持单继承,也支持多层继承,Object是所有类的父类(要么直接继承Object,要么就间接继承Object)
- 父类定义了共性内容,子类定义该类的个性内容
- 继承的意义:代码复用
- 子类继承父类后,(子类就是”父类“ is-a)子类会继承父类的一些属性和方法,子类可以直接访问父类非私有的成员属性和成员方法
- 父类的构造方法、静态方法不会被子类继承
- 父类可以使用自己的属性及行为,但是不可以使用子类新拓展的属性和行为.
- 父类的私有成员属性、私有成员方法会被子类继承,私有成员属性可以通过公开的getter/setter来访问,私有成员方法子类访问不到,但是会被子类继承(理解:父亲给儿子一个保险箱,但是没给钥匙,但儿子确实继承了这个保险箱,只是打不开而已)
- 注意事项:继承中子父类构造方法调用顺序(先父后子)
- 在每次创建子类对象时,我们先初始化父类内容,再初始化其子类的内容。在子类对象的内存空间中,会开辟一块父类空间,用来存父类中的内容,这样便可以包含父类的成员,如果父类成员是非私有的,那么子类可以直接使用。(创建子类对象时,只是在子类空间中开辟了一块父类空间,但是并没有创建父类的对象)
继承的特殊点:
- 构造方法不会被继承(子类在创建对象时,会通过super访问父类的构造方法,但是父类的 构造方法没有被子类继承)
- 静态成员不会被继承(静态成员属于整个类,是共享的)
- 私有成员会被继承(理解:相当于父类给了子类一个“保险箱”,但是没有给钥匙,但是子类继承了父类的“保险箱”,只是没有访问权限而已)
什么是多态
-
面向对象的三大特性之一
-
最终体现形态为:父类的引用变量指向子类对象(子类实例)
-
多态代码格式: 父类类型变量名 = new 子类类型();
-
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态
-
多态的使用场景:
1.为变量赋值时使用多态,达到父类应用指向子类对象的赋值
2.直接为变量赋值
3.调用方法时,为方法参数赋值
4.方法返回值,可以定义父类类型,但是返回子类对象.当该方法被调 用 时,用父类类型接收
-
多态的好处:大大提高了程序的扩展性;提高了程序的复用性
-
多态的弊端:多态编译阶段是看左边父类类型的,如果子类有些独有的功能,此时多态的写法就无法访问子类独有功能了。
-
多态参数:实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。
-
多态转型:
向上转型: 多态本身是子类类型向父类类型向上转型
使用格式:父类类型 变量名 = new 子类类型();
如:Person p = new Student();
向下转型(使用强制类型转换):
使用格式:子类类型 变量名 = (子类类型) 父类类型的变量;
父类类型 f = new 子类类型();
子类类型 z = (子类类型)f;
如:Student stu = (Student) p; //变量p 实际上指向Student对象
instanceof关键字:用来判断运行期类型;判断对象是否属于某种数据类型
关联关系 has-a
-
对象和对象之间的连接
-
代码表现形式:一个类做为另一个类的属性存在(即“有”的关系)
-
意义:代码复用
分类:
一对一关联 oo 关联一个对象
一对多关联 om 关联数组或者关联集合
单向关联
双向关联
强关联(组合关系):随着对象创建而创建,随着对象销毁而销毁
弱关联(聚合关系):不会随着对象的创建而创建,不会随着对象的销毁而销毁
依赖关系 use-a
- 含义:指一个类A使用到了另一个类B(比如说一个类做为一个类中方法的形参出现)
- 特性:这种关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
对比this和super
super关键字:
- 作用:调用执行父类的成员,但是super并不是父类的对象
- 子类中默认提供super(),调用执行父类中的无参构造方法
- super(name, age); 调用执行父类中的有参构造方法
- 默认存在在子类构造方法的第一行,并且只能在构造方法的第一行
- super调用父类的成员方法,调用父类的成员变量
this关键字:
- 当前正在创建的对象,当前正在使用的对象
- this() 调用本类中无参的构造方法
- this(name,age) 调用本类中有参的构造方法 ,但是两者不能互相调用
- this调用本类的成员方法,调用本类的成员变量
对比 | 区别 |
---|---|
this | 代表所在类的对象引用 (理解:方法被哪个对象调用,this就代表那个对象) 访问本类的成员变量或者成员方法,是一个对象 |
super | 访问父类的成员变量或者成员方法,不是一个对象 |
一般会遵循一个大原则:就近原则 局部 > 本类成员 > 父类成员 |
static关键字
- 含义:静态
- static修饰变量和方法都是属于类的,不再属于某一个特定的对象(直接通过类名点来访问,不需要创建对象来访问,可以但没必要);没有static修饰的变量和方法都是属于类的每一个对象(需要创建对象后,通过对象名点来访问)
- 静态变量和方法会随着类的加载而加载,存放在方法区中的静态区(全局区)中
final关键字
- 含义:用于修饰不可改变的内容,不可改变、最终的意思,可以修饰类、变量、方法
- 修饰类:类不能被继承
- 修饰方法:方法不能被重写
- 修饰变量:变量能且只能被赋值一次
抽象类 abstract
-
抽象类用来描述一种类型应该具备的基本特征与功能,具体如何去完成这些行为由子类通过方法重写来完成
-
不能被实例化,不能创建对象,只能做为模板类等待被继承
-
抽象类中可以有构造方法、成员属性、抽象方法(没有方法体)
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类
-
抽象类中构造方法的作用:供子类创建对象时(默认的super()),初始化父类成员使用
-
抽象类的实现类要求:要么重写抽象父类的所有抽象方法,要么就做为一个抽象类等待被继承
-
抽象类存在的意义是为了被子类继承,抽象类体现的是模板思想
抽象类与抽象方法
抽象类 abstract class
1.抽象类中仍然可以定义成员变量、成员方法、构造方法
2.抽象类不能被实例化(不能通过new关键字创建实例化对象),只能当做模板类存在,等待被继承
3.抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类
4.抽象类一旦被继承,要么子类实现抽象类中全部的抽象方法;要么子类也变成抽象类
抽象方法 abstract修饰的方法
1.抽象方法没有方法体 public abstract void/返回值类型 方法名();
2.一旦类中有抽象方法,则当前类一定是抽象类
注意事项:
-
抽象类一定是个父类,因为抽象类是不断抽取共性需求而来的
-
final与abstract不可以一起使用
-
抽象类构造方法存在的意义:子类创建对象时,子类构造方法中会通过默认的super语句调用抽象父类的构造方法,为抽象父类中的成员变量赋值初始化;而赋好值的成员变量可以被子类对象使用
-
设计时由具体类抽取出抽象类,而开发阶段应该先定义抽象父类,再根据不同需求由父类定义子类
-
单例设计模式
- 将构造函数私有化,使其不能在类外通过new创建对象
- 在类内部产生一个唯一的实例化对象,并将其封装为private static类型的成员变量
- 定义一个公开的静态方法,返回给外界唯一的对象
- 分类:饿汉单例设计模式、懒汉单例设计模式
内部类
1.内部类基本概念
- 内部类就是在一个类中定义另一个类,是一个相对概念
- 内部类分为:成员内部类和局部内部类
- 定义内部类的时候,和正常定义类的过程一样,同样包含各种修饰符、继承与实现关系等
- 内部类可以直接访问外部类的所有成员
- 外部类编译后,在方法区中会出现两个class文件
- (注:在日常的企业级开发中,我们很少会使用到内部类来实现业务逻辑)
- 可以使用的修饰符:访问权限修饰符、static、final、abstract
2.匿名内部类
使用:在创建一个类时没有类名,简化代码时创建,在实现一个接口或new一个类的实例 化对象时使用匿名内部类是局部内部类的一种
过程:临时定义一个类型的子类,定义后立刻创建刚刚定义的这个类的对象
目的:匿名内部类是创建某个类型子类对象的快捷方式,我们为了临时定义一个类的子类, 并创建这个子类的对象而使用匿名内部类
理解:将定义子类与创建子类对象两个步骤由一个格式一次完成。虽然是两个步骤,但是两 个步骤是连在一起的、即时的。匿名内部类如果不定义变量引用,则也是匿名对象。
格式:
new 父类(){
//重写需要重写的方法
};
3.静态内部类
定义:在一个类的内部声明一个用static修饰的类,当你使用内部类时,可以通过外部类访 问,和使用静态成员属性、静态成员方法一样
定义格式:
public class Outer{
static class Inner{
//其他代码
}
}
访问格式:
//同类中可以省略外部类名访问
Inner x = new Inner();
//不同类中
Outer.Inner i = new Outer.Inner();
4.成员内部类
定义:在一个类的内部申明一个类,当你使用内部类时,可以通过外部类对象访问,就跟操 作成员属性、成员方法一样。
定义格式:
public class Outer{
class Inner{
//其他代码
}
}
访问格式:
Outer.Inner x = new Outer().new Inner();
5.局部内部类
定义:在一个类的方法中申明内部类,当你调用这个方法时,才可以使用内部类(用的少)
定义格式:
public class Outer{
public void method{
class Inner{
//其他代码
}
}
}
访问格式: 只能在外部类的方法中创建对象并访问。
代码块
1.静态代码块
定义:必须有static修饰,必须放在类下。与类一起加载执行。
格式:
static{
// 执行代码
}
特点:
- 每次执行类,加载类的时候都会先执行静态代码块一次。
- 静态代码块是自动触发执行的,只要程序启动静态代码块就会先执行一次。
- 作用:在启动程序之前可以做资源的初始化,一般用于初始化静态资源
2.实例代码块
定义:没有static修饰,必须放在类下。与对象初始化一起加载。
格式:
{
// 执行代码
}
特点:
-
无static修饰。属于对象,与对象的创建一起执行的。
-
每次调用构造器初始化对象,实例代码块都要自动触发执行一次。
-
实例代码块实际上是提取到每一个构造器中去执行的。
-
作用:实例代码块用于初始化对象的资源。
java
public class Outer{
public void method{
class Inner{
//其他代码
}
}
}
访问格式: 只能在外部类的方法中创建对象并访问。
# 代码块
## 1.静态代码块
定义:必须**有static修饰**,必须放在类下。**与类一起加载执行**。
格式:
```java
static{
// 执行代码
}
特点:
- 每次执行类,加载类的时候都会先执行静态代码块一次。
- 静态代码块是自动触发执行的,只要程序启动静态代码块就会先执行一次。
- 作用:在启动程序之前可以做资源的初始化,一般用于初始化静态资源
2.实例代码块
定义:没有static修饰,必须放在类下。与对象初始化一起加载。
格式:
{
// 执行代码
}
特点:
-
无static修饰。属于对象,与对象的创建一起执行的。
-
每次调用构造器初始化对象,实例代码块都要自动触发执行一次。
-
实例代码块实际上是提取到每一个构造器中去执行的。
-
作用:实例代码块用于初始化对象的资源。