这是我的Java学习笔记,从面向对象开始记录,一直会更新的。这个笔记是根据某站《java入门到起飞》所作。
java学习笔记
1.面向对象
面向对象的思想是:面向对象的思想是万物皆为对象 ,既任何事物都能封装成对象 。
- 面向:拿,找
- 对象:能干活的东西
- 面向对象编程:拿东西过来做对应的事情
1.1设计对象并使用
- 类和对象
类(设计图):是对象共同特征的描述
对象:是真实存在的具体的东西
在java中,必须先设计类,才能获得对象
public clsaa 类名{
1.成员变量(代表属性,一般是名词)
2.成员方法(代表行为,一般是动词)
3.构造方法(作用:在创建对象的时候给成员变量进行赋值)
4.代码块(以后学)
5.内部类(以后学)
}
如何得到类的对象(创建对象)
类名 对象名(自定义名称) = new 类名();
如何使用对象
访问属性:对象名.成员变量
访问行为:对象名.方法名(…)
- 类的几个补充注意事项
-
用来描述一类事物的类,专业叫:javabean类。
在javabean类中,是不写main方法的
-
在以前,编写main方法中的类,叫做测试类。
我们可以在测试类中创建javabean类的对象并进行赋值调用。
1.2封装
对象代表什么,就得封装对应的数据,并提供数据对应的行为
- 通俗一点就是:如何正确的设计对象的属性和行为
- 降低学习成本,可以少记,不用记对象有那些方法,需要的时候找就行
1.2.1private
- 是一个权限修饰符
- 可以修饰成员(成员变量和成员方法)
- 被private修饰的成员只能在本类中才能访问
通俗一点就是保证数据的安全性
public class GirlFriend {
//定义一个女朋友类
//成员变量
private String name;
private int age;
private String gnder;
//针对私有化的成员变量要提供set和get方法
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
public void setAge(int a){
//判断输入的年龄是否合法
if (a > 18 && a < 50){
age = a;
}else{
System.out.println("输入的年龄不合法");
}
}
public int getAge(){
return age;
}
public void setGnder(String g){
gnder = g;
}
public String getGnder(){
return gnder;
}
}
- 针对private修饰的成员变量,如果要被其他类使用,提供相应的操作
- 提供”setXXX(参数)“用于给成员变量赋值,方法用public修饰
- 提供”getXXX(参数)“用于获取成员变量的值,方法用public修饰
1.2.2this关键字
- 就近原则
public class test1 {
//成员变量和局部变量的作用范围
private int a = 10;
public void method() {
int a = 20;
System.out.println(a);//本身遵循的原则:就近原则(谁近用谁)
System.out.println(this.a);//this调用本类中的方法,也就是类中的成员变量
}
}
- this的作用?
可以区别成员变量和局部变量
-
this
的本质和内存图本质:代表方法调用者的地址值。
1.3构造方法
构造方法也叫作构造器、构造函数
-
构造方法的作用:在创建对对象的时候,由虚拟机自动调用,作用是给成员变量进行初始化(赋值)。
-
构造方法有几种,各自的作用是什么?
-
无参数构造方法:初始化对象时,成员变量的数据均采用默认值。
-
有参数的构造方法:在初始化对象时,同时可以为对象进行赋值。
-
-
构造方法的注意事项。
-
任何类定义出来,默认就自带无参数构造器,写不写都有。
-
一旦定义了有参数构造器,无参数构造器就没有了,此时就需要自己写出无参数构造器了。
-
建议在任何时候都要手动写上空参和带全部参数的构造方法。
-
-
构造方法的特点
- 方法名与类名相同,大小写也要一致
- 没有返回值类型,连void都没有
- 没有具体的返回值(不能由return带回结果数据)
-
构造方法的格式
public class Student{
修饰符 Student(参数){
方法体;
}
}
- 构造方法的执行时机
- 创建对象的时候由虚拟机调用,不能手动调用构造方法
- 每创建一次对象,就会调用一次构造方法
1.4标准的javabean
-
类名要见名知意
-
成员变量使用private修饰
-
提供至少两个构造方法
-
无参构造方法
-
带全部参数的构造方法
-
-
成员方法
-
提供每一个成员变量对应的setXXX() / getXXX()
-
如果还有其他行为,也要写上
-
1.5对象内存图
- Java内存分配介绍
-
栈 字节码文件加载时进入的内存
-
堆 方法运行时所需要进入的内存,变量也是在这里
-
方法区 new出来的东西会在这块内存中开辟新空间并产生地址
-
-
StringTable(串池):简单理解:字符串常量池,只有直接赋值的方式才能存储在串池中。new关键字出来的不在这个里面,在堆内存中。
public class StringDemo {
public static void main(String[] arr){
String s1 = "abc";
String s2 = "abc";
}
}
当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在,不存在:创建新的。存在:复用
- 一个对象的内存图
- 两个对象的内存图
- 两个引用指向同一个对象
1.6基本数据类型和引用数据类型
基本数据类型:数据值是存储在自己的空间中(栈内存中)
- 整数类型
- 浮点数类型
- 布尔类型
- 字符类型
特点:赋值给其他变量,也是赋的真实的值。
引用数据类型:数据值时存储在其他空间中,自己空间存储的是地址值。
- 除以上4种类型,其他所有都是引用数据类型
特点:赋值给其他变量,赋的是地址值。
1.7成员变量和局部变量的区别
成员变量:类中方法外的变量
局部变量:方法中的变量
区别 | 成员变量 | 局部变量 |
---|---|---|
类中的位置不同 | 类中,方法外 | 方法外,方法的申明上(形参) |
初始化值不同 | 有默认的初始化值 | 没有,使用前需要完成赋值 |
内存位置不同 | 堆(中对象的)内存 | 栈(中方法的)内存 |
生命周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的运行而消失 |
作用域 | 整个类中有效 | 当前方法中有效 |
1.8API和API帮助文档
API:应用程序接口
API帮助文档:帮助开发人员更好的使用API和查询API的一个工具。
==API:目前是JDK中提供的各种功能的Java类。==就是别人已经写好的东西,我们不需要编写,直接使用即可。
2.String
String概述:java.lang.String类代表字符串,java程序中的所有字符串文字(列如"abc")都为此类的对象。
注意点:字符串的内容是不会发生改变的,它的对象在创建后不能被更改。
2.1创建String对象的两种方式
- 直接赋值
java
String name = "大帅逼薛朝阳";
- new
- 根据字符数组,创建字符串对象
//传递一个字符数组,根据字符数组的内容再创建一个新的字符串对象
char[] chs = {'a','b','c'};
String s = new String(chs);
System.out.println(s);//abc
- 根据字节数组,创建字符串对象
//传递一个字节数组,根据字符数组的内容再创建一个新的字符串对象
byte[] bytes = {97,98,99,100};
String s = new String(bytes);
System.out.println(s);//abcd
2.2java中常用的方法(比较)
2.2.1==号比较的是什么?
- 基本数据类型比较的是数据值
int a = 10;
int b = 10;
System.out.println(a == b);//true
- 引用数据类型比较的是地址值
Strinf s1 = new String("abc");
Strinf s2 = new String("abc");
System.out.println(s1 == s2);//false
- 字符串的比较
String s1 = new String("abc");//记录堆里面的地址值
String s2 = "abc";//记录串池中的地址值
System.out.println(s1 == s2);//false
2.2.2String中的一些方法
-
boolean equals(要比较的字符串) 完全一样结果才是true,否则为false
- boolean equalslgnoreCase(要比较的字符串) 忽略大小写的比较
-
public char charAT(int index):根据索引返回字符
-
public int length():返回字符串的长度
-
数组的长度:数组名.length
-
字符串的长度:字符串对象.length()
-
-
String substring(int beginlndex,int endlndex) 截取
- 注意点:包不包尾,包左不包右 。只有返回值才是截取的小串
- String substring(int beginlndex) 截取到末尾
StringBuilder
StringBuilder可以看作是一个容器,创建之后里面的内容是可变的。
- 作用:提高了字符串的操作效率。
- StringBuilder使用场景
- 字符串的拼接
- 字符串的反转
pubilc StringBuilder构造方法
方法名 | 说明 |
---|---|
pubilc StringBuilder | 创建一个空白可变字符串对象,不含有任何内容 |
pubilc StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
pubilc StringBuilder成员方法
方法名 | 说明 |
---|---|
pubilc StringBuilder append(任意类型) | 添加数据,并返回对象本身 |
pubilc StringBuilder reverse() | 反转容器中的内容 |
public int length() | 返回长度(字符出现的个数) |
public String toString | 通过toString()就可以实现把StringBuilder转化为String |
ublic static void main(String[] args) {
//1.创建对象
StringBuilder sb = new StringBuilder();
//2.添加字符串
sb.append("aaa");
sb.append("ccc");
sb.append("ddd");
//现在的sb不是字符串
//3.再把StringBuilder变回字符串
String str = sb.toString();
System.out.println(str);
}
StringJoiner
- StringJoiner跟StringBuilder一样,也可以看作是一个容器,创建之后的内容是可变的。
- 作用:提高字符串的操作效率。而且代码编写特别简洁,但是目前市面上很少有人用。
- JDK8以后才出现的
StringJoiner的构造方法
方法名 | 说明 |
---|---|
public StringJoiner(间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
public StringJoiner(间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号 |
StringJoiner的成员方法
方法名 | 说明 |
---|---|
public StringJoiner add(添加的内容)注:目前为止只能添加字符串 | 添加数据,并返回对象本身 |
public int length() | 返回长度(所有字符出现的个数) |
public String toString() | 返回一个字符串(该字符串就是拼接之后的结果) |
2.2.3字符串的原理
- 扩展底层原理:字符串存储的内存原理
- 直接赋值会复用字符串常量池中的
- new出来的不会复用,而是开辟一个新的空间
- 扩展底层原理:==号比的到底是什么?
- 基本数据类型比较数据值
- 引用数据类型比较地址值
- 扩展底层原理:字符串拼接的底层原理
- 如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串。
- 如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。
- 扩展底层原理:StringBuilder提高效率原理图
- 所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,节约内存。
- 扩展底层原理StringBuilder源码分析(容量:最多装多少。长度:已经装了多少)
- 默认创建一个长度为16的字节数组。
- 添加内容长度小于16,直接存。
- 添加的内容大于16会扩容(原来的容量*2+2)
- 如果扩容后还不够,以实际长度为准。
3.集合
3.1集合与数组的区别
- 长度
数组的长度固定。可以存基本数组类型,可以存引用数据类型。
- 存储类型
集合长度可变。可以存引用数据类型,基本数据类型要变成包装类才可以存储。
3.2Arraylist成员方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素,返回值表示是否添加成功 |
boolean remove(E e) | 删除指定元素,返回值表示是否删除成功 |
E remove(int index) | 删除指定索引的元素,返回被删除的元素 |
E set(int index,E e) | 修改指定索引下的元素,返回原来的元素 |
E get(int index) | 获取指定索引的元素 |
int size() | 集合的长度,也就是集合中的元素个数 |
3.2.1基本数据类型对应的包装类
byte | Byte |
---|---|
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
4.面向对象进阶
4.1static(共享)
4.1.1三种类(javabean类、测试类、工具类)
javabean类:用来描述一类事物的类。比如,Student、teacher,dog、cat等。
测试类:用来检查其他类是否书写正确,带有main方法的类,是程序的主入口。
工具类:不是用来描述一类事物的,而是帮助我们做一些事情的类。
4.1.2工具类
- 类名见名知意
- 私有化构造方法(只私有化一个空参的构造方法,因为工具类不是描述一类事物的类,没有必要创建带全部参数的构造方法)
4.1.2static的注意事项
- 静态方法只能访问静态变量和静态方法(静态方法中,只能访问静态)
- 非静态方法可以访问静态变量和静态方法,也可以访问非静态的成员变量和非静态的成员方法(非静态可以访问所有)
- 静态方法中是没有this关键字(静态表示共享,和某一个对象没有太大关系)
4.2继承
- 什么是继承、继承的好处?
继承是面向对象三大特征之一,可以让类跟类之间产生子父关系。可以把多个子类中冲重复的代码抽取到父类中,子类可以直接使 用,减少代码冗余,提高代码的复用性。
- 继承的格式?
public clsaa 子类 extends 父类 {}
- 继承后子类的特点?
子类可以得到父类的属性和行为,子类可以使用。
子类可以在父类的基础上新增其他功能,子类更强大。
- 什么时候用继承?
当类和类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码
继承的特点
- java只能单继承:一个类只能继承一个直接父类。
- java不支持多继承,但支持多层继承。
- java中所有的类都直接或者间接继承于Object类。
###子类到底能继承父类中的哪些内容?
公共public | 私有private | |
---|---|---|
构造方法 | 不能 | 不能 |
成员变量 | 能 | 能 |
成员方法 | 虚方法表(能) | 不是虚方法(不能) |
- 继承中成员变量访问的特点:就近原则。
先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。
- 如果出现重名的成员变量怎么办?
Systen.out.println(name);//从局部位置开始往上找
Systen.out.println(this.name);//从本类成员位置开始往上找
Systen.out.println(super.name);//从父类成员位置开始往上找
方法重写注意事项和要求(建立在继承上的)
- 重写方法的名称、形参列表必须与父类中的一致。
- 子类重写父类方法时,访问权限子类必须大于等于父类
- 子类重写方法时,返回值类型必须小于等于父类。
- 建议:重写的方法尽量和父类保持一致。
- 只有添加到虚方法表中的方法才能被重写。
虚方法
不能被private,static,final修饰的方法
小结
- 继承中成员方法的访问特点:
- this调用:就近原则。
- super调用:直接找父类。
- 什么时方法重写?
- 在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类的这个方法是重写的方法。
- 方法重写建议加上哪个注解,有什么好处?
- @Override注解可以校验重写是否正确,同时可读性好
- 重写方法有哪些基本要求?
- 子类重写的方法尽量跟父类中的方法保持一致。
- 只有虚方法表里面的方法可以被重写。
- 方法重写的本质?
- 覆盖虚方法表中的方法。
继承中构造方法的访问特点
- 子类不能继承父类的构造方法,但是可以通过super调用
- 子类构造方法的第一行,有一个默认的super();
- 默认先访问父类中无参的构造方法,再执行自己。
- 如果想要方法中父类的有参构造,必须手动书写。
this、super使用总结
- this:理解为一个局部变量,表示当前方法调用者的地址值
- super:代表父类存储空间
4.3多态
Student s = new Student();//学生形态
Preson p = new Student();//人的形态
- 什么是多态?
同类型的对象,表现出的不同形态。(对象的多种形态)
- 多态的表现形式?
父类类型 对象名 = 子类对象;
- 多态的前提
- 有继承关系
- 有父类引用指向子类对象
Fu f = new zi ();
- 有方法重写
- 多态的好处?
使用父类作为参数,可以接受所有子类对象,体现多态的扩展性与便利。
多态中调用成员的特点
- 变量调用:编译看左边,运行也看左边
- 方法调用:编译看左边,运行看右边
多态的优势和弊端
- 多态的优势
方法中,使用父类作为参数,可以接受所有子类对象
-
多态的弊端是什么?
不能使用子类的特有功能
-
引用数据类型转换,有几种方式?
自动类型转换、强制类型转换
Person p = nwe Student();//自动类型转换
Student s = (Student)p;//强制类型转换
- 强制类型转换能解决什么问题?
- 可以转换成真正的子类类型,从而调用子类特有功能
- 转换类型与真实类型不一致会报错。
- 转换的时候用instanceof关键字进行判断
4.4包、final、权限修饰符、代码块
- 什么是包?
包就是文件夹。用来管理各种不同功能的java类,方便后期代码的维护。
- 包名的规则:公司域名反写 + 包的作用,需要全部用英文小写,见名知意。com.itheima.domain
- 使用其他类的规则
- 使用同一个包中的类时,不需要导包。
- 使用java.lang包中的类时,不需要导包。
- 其他情况都需要导包。
- 如果同时使用两个包中的同类名,需要用全类名(包名 + 类名)。(com.itheima.domain.Student)
final
方法 | 表示该方法是最终方法,不能子类被重写 |
---|---|
类 | 表示该类是最终类,不能被其他类继承 |
变量 | 改为常量,只能被赋值一次 |
注意事项
final 修饰基本数据类型:记录的数据值不能发生改变
final 修饰引用数据类型:记录的地址值不能发生改变,对象内部属性值的是可以改变的
权限修饰符的分类
有四种作用范围由小到大(private < default < protected < public)
修饰符 | 同一个类中 | 同一个包中其他类 | 不同包下的子类 | 不同包下的无关类 |
---|---|---|---|---|
private | √ | |||
default | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
- public : 对所有类可见
- protected : 对同一包内的类和所有子类可见
- default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符
- private : 在同一类内可见
权限修饰符的使用规则
实际开发中,一般只用private和public
- 成员变量私有
- 方法公开
特例:如果方法中的代码是抽取其他方法中的共性代码,这个方法一般也私有
代码块
-
代码的分类:
- 局部代码块、构造代码块、静态代码块
-
局部代码块的作用
- 提前结束变量的生命周期(已淘汰)
-
构造代码块的作用
- 抽取构造方法中的不重复代码(不够灵活)
-
静态代码块的作用
- 数据的初始化(重点)
4.5抽象类和抽象方法
抽象类的作用是什么样?
-
抽取共性时,无法确定方法体,就把方法定义为抽象的。
-
强制让子类重写该抽象方法
-
抽象方法所在的类,必须时抽象类
抽象类和抽象方法的格式?
public abstract 返回值类型 方法名(参数列表);
public abstract class 类名{};
抽象类和抽象方法注意事项
-
抽象类不能实例化(创建对象)
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
可以有构造方法(作用:当创建子类对象时,给属性进行赋值的)
-
抽象类的子类
- 要么重写抽象类中的所有抽象方法(通常用这个)
- 要么是抽象类
4.6接口
接口是一种规则,是对行为的抽象
接口的定义和使用
- 接口用关键字interface来定义。 public intterface 接口名{}
- 接口不能实例化
- 接口和类之间是实现关系,通过implements关键字来表示
public class 类名 implements 接口名{}
- 接口的子类(实现类)
要么重写接口中的所有抽象方法(通常用这种)
要么是抽象类
注意1. 接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 inplements 接口名1,接口名2{}
注意2. 实现类还可以在继承一个类的同时实现多个接口
public class 类名 extends 父类 implements 接口名1,接口名2{}
接口中成员的特点
- 成员变量
只能是常量
默认修饰符:public static final
- 构造方法
没有
- 成员方法
只能是抽象方法
默认修饰符:public abstract
接口和类之间的关系
- 类和类的关系
继承关系,只能单继承,不能多继承,但是可以多层继承
- 类和接口之间的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
- 接口和接口之间的关系
继承关系,可以单继承,也可以多继承
4.7接口的扩展
JDK8开始接口中新增的方法
-
JDK7以前:接口中只能定义抽象方法。
-
JDK8的新特性:接口中可以定义有方法体方法。(默认的方法或静态的方法)
-
允许在接口中定义默认方法,需要用关键字default修饰(作用:解决接口升级的问题)
-
接口中默认方法的定义格式:
- 格式:public default 返回值类型 方法名(参数列表){}
- 范例:public default void show(){}
-
接口中默认方法的注意事项:
-
默认方法不是抽象方法,所以不强制被重写。但如果被重写,重写的时候去掉default关键字
-
public可以省略,default不能省略
-
-
接口中静态方法的定义格式:
- 格式:public static 返回值类型 方法名 (参数列表){}
- 范例:public static void show(){}
-
接口中静态方法的注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public 可以省略,static不能省略
- JDK9的新特性:接口中可以定义私有方法
- 接口中私有方法的定义格式:
- 格式1:private 返回值类型 方法名(参数列表){} (给默认方法用的)
- 范例:private void show(){}
- 格式2:private static 返回值类型 方法名(参数列表){} (给静态方法用的)
- 范例:private static void show(){}
接口的应用
- 接口代表规则,是行为的抽象。想要哪个类拥有一个行为,就让这个类实现对应的接口就可以了。
- 当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。
适配器设计模式
设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验总结,使用设计模式是为了可重用代码、让代码容易被他人理解保证代码可靠性、程序的重用性
简单理解:设计模式就是各种套路
适配器设计模式:解决接口与接口实现类之间的矛盾问题
- 当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以适配器模式
- 书写步骤:
- 编写中间类XXXAdapter,实现对应的接口,让接口中的抽象方法进行空实现。
- 让真正的实现类继承中间类,并重写需要用的方法,中间类是没方法体的,所以创建中间类的对象是没有意义的,中间类就要用abstract修饰。
- 如果这个实现类还有其他父类,就用中间类来继承你想要的父类,再用实现类来继承中间类就可以了。
4.8内部类
什么是内部类?
-
在一个类的里面,在定义一个类
-
举例:在A的类的内部定义B类,B类就被称为内部类
内部类表示的事物是外部类的一部分
内部类单独出现没有任何意义
内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建内部类的对象
成员内部类
- 成员内部类的代码如何书写
- 写在成员位置的(类中方法外),属于外部类的成员。
- 成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等
- 在成员内部类的里面,JDK16之前不能定义静态变量,JDK16才开始可以一定义静态变量。
- 如何创建成员内部类的对象
- 方式一:在外部类中编写方法,对外部提供内部类的对象
- 方式二:直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
- 成员内部类如何获取外部类的成员变量
System.out.println(Outer.this.变量名);
静态内部类
- 什么是静态内部类?
静态内部类是一种特殊的成员内部类
- 直接创建静态内部类对象的方式?
Outer.Innter oi = new Outer.Innter();
- 如何调用静态内部类中的方法?
非静态方法:先创建对象,用对象调用
静态方法:外部类名.内部类名.方法名();
局部内部类
- 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
- 外界是无法直接使用,需要在方法内部创建对象并使用。
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
匿名内部类
- 什么是匿名内部类?
隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。
- 匿名内部类的格式?
new 类名或者接口名(){
重写方法;
};
- 格式的细节
包含了继承或实现,方法的重写,创建对象
整体就是一个类的子类或者接口的实现类对象
- 使用场景
当方法的参数是接口或者类时,
以接口为例,可以传递这个接口的实现对象,
如果实现类只要使用一次,就可以用匿名内部类简化代码。