一、基本数据类型
1. 整型
用于表示没有小数的数值,允许负数。有4种数据类型
类型 | 存储需求 | 取值范围 |
---|---|---|
int | 4字节 | -2^31 ~ 2^31-1 |
short | 2字节 | -2^15 ~ 2^15-1 |
long | 8字节 | -2^63 ~ 2^63-1 |
byte | 1字节 | -2^7 ~ 2^7-1 |
2. 浮点型
浮点型用于表示有小数部分的数值。有2种数据类型
类型 | 存储需求 | 取值范围 |
---|---|---|
float | 4字节 | -3.403E38 ~ 3.403E38 |
double | 8字节 | -1.798E308 ~ 1.798E308 |
3. boolean型
4. char类型
char类型用于表示单个字符
类型 | 存储需求 | 取值范围 |
---|---|---|
char | 2字节 | 0 ~ 65535 |
二、引用数据类型
1. 接口/类/数组
2. 接口与抽象类
抽象类不能被实例化只能被继承
数据类型
接口和抽象类的区别?
什么时候用接口,什么时候用抽象类?
接口和抽象类的区别?
接口:单纯的对行为的一种抽象
抽象类:对一些类的公共部分的抽象
自定义类
1.类的格式
class ClassName {
字段(成员变量);
构造方法;
成员方法;
}
例如:
class Person {
String name;
public Person(){}
public void method(){}
}
2.类的声明
- 声明对象Person名称为person,引用创建的Person类型的对象
Person person = new Person();
类被创建出来时,成员变量(引用类型)会引用null值
- Java10中可以声明一个没有类型的对象,然后根据引用对象的类型来决定类型
var var = new Person();
!> var关键字只能用于局部变量
3.类的使用
- 获取声明好的person对象中的名字,以及执行person对象的method方法
Person person = new Person();
String name = person.name;
person.method();
4.成员方法
- 方法创建的格式
class ClassName {
返回值类型 成员方法名(形参列表){
方法体;
}
}
例如:定义一个需要传入参数且有返回值的方法
class Person {
public int method(String name, int age){
return 1;
}
}
!> 基本数据类型作为参数传递时,形参变量发生改变时,不会影响实参的值,因为各自的内存空间时独立的。而引用数据类型发时改变时都会发生改变,除非改变引用数据类型的指向。
JVM会为每一个方法的调用在栈中分配一个对应的空间,这个空间成为该方法的栈帧。方法调用结束以后,栈帧将被清除。
5.可变长参数
- name参数可以传0-n个参数,可变参数只能放在参数列表末尾
class Person {
public int method(int age, String... name){
return 1;
}
}
6.封装
- 在变量或者方法前加
private
关键字可以将变量或方法变成私有的 - 私有方法和变量只能在当前类的内部使用
- 提供公有的
get/set
方法来修改被private
修饰的变量
对象构造
3.重载
- 若方法名相同,参数列表不同,这样的方法之间构成重载(Overload)
- Java允许重载任何方法,而不只是构造方法
- 要完整的描述一个方法,需要指定方法名以及参数类型,这叫做方法的签名(singnature)。
- 返回类型不是方法签名的一部分,不能有两个方法名相同,参数类型相同,却有不同返回类型的方法。
例如:下面的方法可以构成重载
void show();
void show(int i);
void show(int i, double d);
void show(int i, int j);
void show(double d, int i);
4.this关键字
- 若在构造方法中出现了
this
关键字,则代表当前正在构造的对象 - 若在成员方法中出现了
this
关键字,则代表当前正在调用的对象 - this关键字本质上就是当前类类型的引用变量
5.初始化块
- 一个类的声明中可以包含任意多个代码块,只要类被创建,这些代码块就会被执行
class Person {
String name;
// 初始化代码块
{
name = "hzlim"
}
}
- 静态字段如果需要复杂的初始化过程,可以使用静态初始化代码块
class Person {
static String name;
// 初始化代码块
static {
name = "hzlim"
}
}
- 初始块会在构造方法之前执行,静态初始块会在类被加载内存方法区的时候执行
递归
- 使用递归必须有递归的规律以及退出条件
- 使用递归必须使得问题简单化而不是复杂化
- 若递归影响到程序的执行性能,则使用递推取代之
public static int fibonacci(int n) {
return 1 == n || 2 == n ? 1 : fee(n - 1) + fee(n - 2);
}
递推:
public static int fibonacci(int n) {
int ia = 1;
int ib = 1;
for (int i = 0; i <= n; i++) {
int ic = ia + ib;
ia = ib;
ib = ic;
}
return ib;
}
static关键字
1.静态成员
- 被
static
修饰的字段的值被整个类共享 - 静态字段:被
static
修饰的字段称为静态字段,也叫类字段 - 静态常量:被
final static
修饰的字段称为静态常量,当静态常量被赋值时将不能被修改 - 静态方法:被
static
修饰的方法称为静态方法,静态方法可以通过类名.方法名
来调用 - 静态方法只能访问被
static
修饰的方法和字段
2.main方法
- main方法不对任何对象进行操作。事实上,在启动程序时还没有任何对象。静态的main方法将执行并构造程序所需要的对象
- 可以在运行时添加参数传入args数组中例如
java Test 参数1 参数2
3.单例模式
继承
1.子类
- 在Java语言中使用的
extend
关键字来表示继承关系 - 被继承的类被称为称为超类(superclass)、基类(base class)或父类(parent class),继承父类的新类称为子类(subclass)、派生类(derived class)
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承但是不能直接访问
2.方法重写
- 当父类的方法对于子类不适用时,子类需要提供一个新的方法来覆盖父类的这个方法,这种方式叫方法的重写(Override)
public class Teacher extends Person{
@Override
public void show(){
// 调用父类的show方法
super.show();
}
}
- 要求方法名相同、参数列表相同以及返回值类型相同,从Java5开始运行返回子类类型
- 要求方法的访问权限不能小,可以相同或者变大
- 要求方法不能抛出更大的异常(异常机制)
3.子类构造
- 由于子类不能访问父类的私有字段,所以要利用super关键字来调用父类的构造器,用来初始化从父类继承的成员变量
public Teacher(){
// 调用父类无参构造器
super();
}
- 子类的构造器没有显式的使用
super
关键字来调用父类的构造方法,将会自动调用父类的无参构造方法 - 子类没有显式的调用父类的构造方法,而且父类也没有无参构造方法,Java将会抛出异常
- 子类可以通过
super(参数)
来调用父类其他的构造方法
6.final关键字
final
关键字修饰类体现在该类不能被继承final
关键字修饰成员方法体现在该方法不能被重写但是能被继承final
关键字修饰成员变量体现在该变量必须初始化且不能改变
7.强制类型转换
- 只能在继承层次内进行强制类型转换
- 在父类强制转换成子类前,应该使用
instanceof
进行检查是否是该子类
8.抽象类抽象方法
- 抽象方法主要指不能具体实现的方法并且使用
abstract
关键字修饰,也就是没有方法体 - 抽象方法格式:访问权限
abstract
返回值类型 方法名(形参列表); - 抽象类主要指不能具体实例化的类并且使用
abstract
关键字修饰,也就是不能创建对象 - 抽象类中可以没有抽象方法,也可以有抽象方法
- 拥有抽象方法的类必须是抽象类,因此真正意义上的抽象类应该是具有抽象方法并且使用
abstract
关键字修饰的类 - 抽象类的实际意义不在于创建对象而在于被继承
- 当一个类继承抽象类后必须重写抽象方法,否则该类也变成抽象类,也就是抽象类对于子类具有强制性喝规范性,因此叫做模版方法模式
9.访问控制
修饰符 | 本类 | 同包类 | 子类 | 其他类 |
---|---|---|---|---|
public | ||||
protected | ||||
默认(default) | ||||
private |
10.包
- 在定义一个类时,还需要指定一个包,格式:package 包名;
- 包名的命名规范是,域名或组织反写+项目名称+模块名称,如:cn.hzlim.base.demo1
- 可以使用
import
关键字导入包,从Java5开始也可以导入静态成员
11.继承注意事项
- 将公共操作和字段放在父类中
- 子类尽量不要使用
protected
修饰过的变量,因为这样破坏了封装性 - 使用继承必须满足逻辑关系:子类is a父类,也就是不要滥用
- 覆盖方法时,不要改变预期行为
- 使用多态而不要使用类型信息
- 不要滥用反射
接口
1.基本概念
- 接口就是一种比抽象类还要抽象的类,体现在所有方法都为抽象方法
- 定义类的关键字是
class
,而定义接口的关键字是interface
- 接口中的所有抽象方法都自动是
public
方法
2.接口的属性
- 接口不能通过new来实例化,但是能声明接口变量
- 可以使用
instanceof
来检查一个类是否实现了某个接口 - 接口可以通过继承其他接口来扩展接口
- 接口可以包含常量,默认被
public static final
修饰 | 名称 | 关键字 | 关系 | | —- | —- | —- | | 类和类之间的关系 | 使用extends关键字表达继承关系 | 支持单继承 | | 类和接口之间的关系 | 使用implements关键字表达实现关系 | 支持多实现 | | 接口和接口之间的关系 | 使用extends关键字表达继承关系 | 支持多继承 |
3.静态和私有方法
- 在Java8中接口允许增加静态方法
- 在Java9中接口方法可以是
private
public interface InterfaceTest {
public static void test1(){}
private void test2(){}
}
4.默认方法
- Java8可以为接口方法提供一个默认实现,但必须由
default
修饰,默认方法可能被其他实现覆盖 - 默认方法可以调用其他方法
public interface InterfaceTest {
public default void test2(){}
}
5.默认方法冲突
- 接口冲突:如果一个类实现了2个接口,并且继承了2个相同的方法,则必须覆盖这个方法来解决冲突
public class Student implements Person,Name{
@Override
public void getName() {
Name.super.getName();
}
}
public interface Person {
default void getName(){}
}
public interface Name {
default void getName(){}
}
- 超类优先:如果一个类继承了一个抽象类,又实现了一个接口,并从2者继承了相同的方法,那么接口的方法将被忽略,这就是“类优先”规则
6.接口和抽象类区别
- 定义抽象类的关键字是
abstract class
,而定义接口的关键字是interface
- 继承抽象类的关键字是
extends
,而实现接口的关键字是interface
- 继承抽象类支持单继承,而实现接口支持多实现
- 抽象类中可以有构造方法,而接口中不可以有构造方法
- 抽象类中可以有成员方法,而接口中只可以有抽象方法
- 抽象类中增加方法时子类可以不用重写,而接口中增加方法时实现类需要重写(Java8以前的版本)
- 从Java8开始接口中允许出现非抽象方法的静态方法,但非抽象方法需要使用
default
关键字修饰 - 在Java9中接口方法可以是
private
枚举类
1.使用方法
- 枚举值就是当前类型,指向本类对象,默认使用
public static final
关键字修饰,采用枚举类型.
来调用 - 枚举类的构造方法必须是
private
修饰的,枚举的构造器默认是私有的 - 每个枚举类型都有一个静态的value方法,方法会返回一个包含所有枚举值的数组
2.枚举类方法
- 所有枚举类都继承自java.lang.Enum类
方法声明 | 功能介绍 |
---|---|
static Enum[] values() |
返回当前枚举类所有对象 |
static Enum valueOf(Class enumClass, String name) |
返回给定类中有指定名字的枚举变量 |
String toString() |
返回枚举常量名 |
int ordinal() |
返回枚举常量在enum声明中的位置,位置从0开始计数 |
int compareTo(E other) |
枚举常量在other之前,返回负数,等于返回0,否则返回正数 |
内部类
- 当一个类的定义出现在另一个类的类体中,这个类就叫做内部类(Inner Class),外部类称为(Outer Class)
- 内部类的作用仅仅是为了某一个类单独服务使用的
1.普通内部类
public class Outer{
public class Inner{
类体;
}
}
- 普通内部类和普通类一样可以定义成员变量、成员方法以及构造方法等
- 普通内部类和普通类一样可以使用
final
或者abstract
关键字修饰 - 普通内部类还可以使用
private
或protected
关键字进行修饰 - 普通内部类需要使用外部外部类对象来创建对象
- 如果内部类访问外部类中与本类同名的成员变量或方法时,需要使用
this
关键字 - 内部类引用外部类变量语法:
OuterClass.this
public class Outer{
private String name;
public class Inner{
public void getName(){
String name = Outer.this.name;
}
}
}
- 其他外部类引用内部类语法:
OuterClass.InnerClass
public class OtherOuter {
public void getInner(){
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
}
}
2.静态内部类
public class Outer{
public static class Inner{
类体;
}
}
- 静态内部类不能直接访问外部类的非静态成员
- 静态内部类可以直接创建对象
- 如果静态内部类访问外部类中与本类内同名的成员变量或方法 时,需要使用
ClassName.
的方式访问
3.局部内部类
public class Outer{
public void method(){
class Inner{
类体;
}
}
}
- 局部内部类只能在该方法的内部可以使用
- 局部内部类可以在方法体内部直接创建对象
- 局部内部类不能使用访问控制符和static关键字修饰
- 局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局部变量的声明周期不同所致
4.回调
- 回调模式是指:如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象;而该方法在运行时会调用到参数对象中所实现的方法(接口中定义的)
public class CallbackClass {
public static void collback(CallbackInterface ci){
ci.show();
}
public static void main(String[] args) {
CallbackClass.collback(new CallbackInterfaceImpl());
}
}
public interface CallbackInterface {
void show();
}
public class CallbackInterfaceImpl implements CallbackInterface{
@Override
public void show() {
System.out.println("接口回调");
}
}
5.匿名内部类
- 接口/父类类型 引用变量名 = new 接口/父类类型() {方法重写};
public static void main(String[] args) {
CallbackInterface ci = new CallbackInterface() {
@Override
public void show() {
System.out.println("回调接口实现");
}
};
CallbackClass.collback(ci);
}
- Java8开始可以用Lamda表达式简化:(参数列表) -> {方法体}
public static void main(String[] args) {
CallbackInterface ci = () -> {
System.out.println("回调接口实现");
};
CallbackClass.collback(ci);
}
更新时间:{docsify-updated}