目录
一、面向对象编程
1. 设计对象并使用
- 类:是对象共同特征的描述。
- 对象: 是真是存在的具体实例。
- 在java中必须先设计类,才能创建对象并使用
创建类
public class 类名{
属性定义
修饰符 数据类型 = 值;
方法定义
修饰符 返回值类型 方法名(参数列表){
}
}
public class Car{
//属性 成员变量
String name;
String price;
//行为 方法
public void start(){
}
public void run(){
}
}
使用类 对象
类名 对象名 = new 类名();
Car c = new Car();
c.name; //访问属性
c.run(); //访问方法
类名大写,驼峰命名规则。 一个java文件可以定义多个类,但是只能一个类是public,而且必须和文件名一致。
public class Phone {
public int Size = 14;
public String Color = "Red";
public String Call(String number){
return "正在呼叫:"+number;
}
}
public static void main(String[] args) {
Phone p = new Phone();
System.out.print(p.Call("13845054318"));
p.Size = 100;
System.out.print(p.Size);
}
2. 对象内存图
首先 main.class 加载到方法区。
在执行Car c 时 会在栈内存中 开辟一块空间。
= new Car();后 会在堆内存开辟一块空间。
设置属性时 c.name=“a”; 会在 堆内存开辟的空间中
堆中的方法存的是引用地址 引用的方法在方法区中。
Car c 中存的是 堆内存中的地址。
当堆内存中的对象,没有被任何变量引用指向时,就会被判定为内存中的垃圾。
3. 构造器
无参构造 任何类默认就自带了无参的构造函数,一旦定义了有参的构造函数,就需要自己写一个无参的构造函数。
public Car(){
}
new Car();
有参构造
public Car(String name,double price){
this.name = name;
this.price = price;
}
new Car("特斯拉",100.00);
4. 封装
面向对象的三大特性:封装,继承,多态。
隐藏具体实现的细节,对外提供可以访问的方式。便于调用者的使用。提高了复用性。
public class Phone {
private int size;
public void setSize(int s){
size = s;
}
public int getSize(){
return size;
}
}
5. this关键字
this代表的是当前对象的地址。区分成员变量和局部变量同名的情况
public class Phone {
private int size;
public void setSize(int s){
int size = 1;
this.size = s;
}
public int getSize(){
return this.size;
}
}
6. javaBean
标准javaBean应该满足如下书写要求。
- 成员变量使用private修饰。
- 提供成员变量对应的get set方法
- 必须提供一个无参的构造函数。
7. 成员变量、局部变量区别
成员变量在类中,存在堆内存中,随着对象的创建而生,对象的消失而消失。
局部变量在方法中,存在栈内存中,随着方法的调用而存在,随着方法的结束而消失。
二、String
1. String类概述
String类定义的变量可以用于存储字符串,同时String提供了很多操作字符串的功能。
//String类是不可变字符串类型,一旦创建后不能被更改,但是内存地址是可以改变的。
String name = "aa";
name = "bb"; //其实是在堆内存中重新创建了一个字符串 将引用地址 重新复制给name变量。
比较
String str = "aa";
String str2 = "aa";
System.out.println(str == str2); //false 引用类型数据,==比较的是对象的地址
System.out.println(str.equals(str2)); //true equals 比较的是对象的内容
2. String类创建对象的2种方式
String str = new String("abcdefghijklmnopq123456"); //实际上创建了两个对象 堆中的字符串常量池一个 堆内存还有一个
String str = "sdfjklsdf"; //双引号创建的字符串对象,在字符串常量池中存储一个
Char[] c = {'a','b','c'};
String str = (c);
byte[] b = {97,98,99};
String str = (b);
String s1 = "abc";
String s2 = "a"+"b"+"c";
s1 == s2 ? //true. java编译优化机制,a+b+c 会直接转成abc 引用地址相同。
3. String类的常用方法
length() 返回字符串长度 字符个数
charAt(index) 获取某个索引处的字符
substring(startIndex,endIndex) 截取字符串 返回从开始到结束的字符串
startsWith(String prefix) 检测是否以此字符串开头
endsWith(String suffix) 检测是否以此字符串结尾
contains(String str) 判断字符串是否包含str字符串
indexOf(String str) 返回制定字符串在字符串中第一次出现的索引 没有返回-1
getBytes() 返回byte数组
toCharArray() 返回字节数组
equals(object obj) 字符串与指定对象比较
equalsIgnoreCase() 比较字符串不考虑大小写
toUpperCase() 转换大写
toLowerCase() 转换小写
replace() 替换字符串,使用的字符串
split() 参数分隔符 返回字符串数组
三、 ArrayList
1. ArrayList概述
ArrayList代表的是集合类,集合是一种容器,与数组相似,集合的大小是不固定的。
ArrayList集合的对象的创建
创建对象 ArrayList<数据类型> 名 = new ArrayList<数据类型>();
ArrayList<String> arr = new ArrayList<String>();
数据类型不能是基本数据类型,必须是引用数据类型。
byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
char -> Character
boolean -> Boolean
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(1); //插入到集合的末尾
nums.add(3);
nums.add(3);
nums.add(3);
nums.add(2,3333); //插入到指定索引
for(int i = 0;i<nums.size();i++){
System.out.println(nums.get(i));
}
2. ArrayList的常用方法
add() 添加元素
get(index) 取出元素 索引取出
size() 返回长度
set(index,element) 修改指定索引的元素
remove(index) 移除指定索引的元素
clear() 清空
四、 static关键字
- static是什么?
static是静态的意思,可以用来修饰成员变量、成员方法。
static修饰成员变量之后称为静态成员变量,修饰方法后称为静态方法。
static修饰后的成员变量,可以被类的所有对象共享(访问、修改)。
public class Tai{
//所有对象共享 静态成员变量 只在内存中有一份
public static int onlineNumber = 160;
public String name;
}
Tai.onlineNumber; //160
Tai tai = new Tai();
tai.onlineNumber ++; //161
- static修饰成员方法
//静态的方法可以直接 类名.方法名调用 不需要实例化
public class tai {
public static void SayTai(){
System.out.println("崩卡崩卡");
}
}
tai.SayTai(); //静态不能调用非静态。
- static注意事项
静态方法只能访问静态成员,不可以直接访问实例成员。
实例方法可以访问静态的成员,也可以访问实例成员。
静态方法中不可以使用this关键字。
代码块
在java类下,使用{}扩起来的代码称为代码块
- 静态代码块
public static void main(String[] args) {
System.out.println("main方法被执行了"); //后执行
System.out.println(name);
}
public static String name;
//静态代码块 与类优先加载一次 自动触发执行
//可以用于初始化静态资源
static{
name = "what";
System.out.println("静态代码块被触发执行了"); //先执行
}
- 构造代码块
每次创建对象,调用构造器执行,在构造器执行前执行。
public class code2 {
//实例代码块 每次构建对象都会被执行一次 在构造器之前执行
{
System.out.println("示例代码块执行"); //先执行
}
public code2(){
System.out.println("构造器执行"); //后执行
}
public static void main(String[] args) {
code2 c = new code2();
}
}
五、 单例设计模式
开发中经常遇到的一些问题,一个问题有多种解决方案,其中最优的方案被总结出来了,称之为设计模式。
单例模式, 可以保证系统中,应用该模式的这个类永远只有一个实例。
- 饿汉单例模式
在用类获取对象的时候,对象已经提前为你创建好了。
首先把构造器私有
然后定义静态变量 new对象
最后定义静态方法 返回此对象
//饿汉单例模式 构造器私有化
public class SingleInstance {
public static SingleInstance instance = new SingleInstance();
//不对外 new对象
private SingleInstance() {
}
public static SingleInstance getInstance(){
return instance;
}
}
//调用时
SingleInstance s1 = SingleInstance.getInstance();
SingleInstance s2 = SingleInstance.getInstance();
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2)); //true
- 懒汉单例模式
在真正需要使用该对象的时候才会去创建。
public class SingleInstance {
//私有化
private static SingleInstance instance; //默认是null
//不对外 new对象
private SingleInstance() {
}
public static SingleInstance getInstance(){
if(instance == null){
instance = new SingleInstance();
}
return instance;
}
}
六、 面向对象:继承
1.继承概述
使用 extends 可以让一个类和另一个类建立父子关系。
public class Student extends People{
Student称为子类、People称为父类。
当子类继承父类后,就可以使用父类的公共属性和方法了
使用集成的好处,提高代码的复用性。
2. 继承设计规范
子类们相同的属性和方法可以放在父类中定义,自己独有的属性和方法定义在子类自己里面。
在堆内存中 一但Student对象初始化,则会创建两块内存空间,一块放父类,一块放子类。
3. 继承的特点
子类可以继承父类的属性和方法,但是子类不能继承父类的构造器。
Java是单继承模式,一个类只能继承一个直接父类。
Java不支持多继承,但是支持多层继承。
Java中所有的类都是Object类的子类。
父类静态成员属于共享成员,但不代表被子类继承。可以直接用。
4. 继承后成员变量、成员方法的访问特点
就近原则
现在子类局部范围找,然后子类成员范围找,最后父类成员范围找,还没找到就报错。
如果子类出现了重名的成员,则优先使用子类的。如果一定要使用父类的则使用super关键字。
5. 继承后 方法重写
在继承体系中,当父类和子类中的方法声明一模一样时,称为方法的重写。
当子类需要使用父类的功能,但父类的功能不满足自己需求时可以重写父类的方法。
@Override重写注解
放在重写的方法上,作为重写是否正确的效验注解。
public class People {
public void say(){
System.out.println("人说大家好");
}
}
public class Student extends People{
public Student(){
super.say();
}
@Override
public void say(){
System.out.println("学生说好");
}
}
Student s = new Student();
s.say();
//人说大家好
//学生说好
6. 继承后 子类构造器的特点
子类中所有的构造器默认都会先访问父类中的无参构造器,然后再执行自己。
public class People {
public People() {
System.out.println("父类无参构造器被执行了");
}
public void say(){
System.out.println("人说大家好");
}
}
public class Student extends People{
public Student(){
super.say();
}
@Override
public void say(){
System.out.println("学生说好");
}
}
Student s = new Student();
//父类无参构造器被执行了
//人说大家好
子类构造器的第一行语句默认都是 super(); 不写也存在。
7. 继承后子构造器访问父有参构造器
子类调用父类有参构造器可以用来初始化父类的数据。
public class People {
public String name;
public People() {
System.out.println("父类无参构造器被执行了");
}
public People(String name){
this.name = name;
}
public void say(){
System.out.println(name+"人说大家好");
}
}
public class Student extends People{
public String name;
public Student(){
super("父类名字");
super.say();
}
@Override
public void say(){
System.out.println("学生说好");
}
}
Student s = new Student();
//父类名字人说大家好
this代表本类本身,super代表父类存储空间的标识。
七、 包
java中的包,其实就是电脑中的文件夹,包中放的是类文件。
命名规则,全部小写,域名反写、com.xxx.web
package david.web; 包的声明 在第一行
导入包
import david.web.Outer; 具体到类名
1.同一个包下的类,互相可以直接访问。
2.不同包下的类,需要先导入包才可以访问。
3.如果一个类中需要用到不用类,而这两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
package com.test;
public class Stu {
}
package com.utils;
public class StringUtils {
public void say(){
System.out.println("say");
}
}
导入
import com.utils.StringUtils;
八、 权限修饰符
用来控制一个成员能够被访问的范围。
可以修饰成员变量,方法,够再起,内部类。
1.仅能在本类中使用 private
2.本包中的类可以访问不加修饰符
3.本包中的类与其他包中的子类可以访问 protected
4.所有包中的所有类 public
一个文件中只能有一个public修饰的类,如果用public修饰则类名必须与文件名相同。
九、final
不可变
可以用来修饰类,类的成员,以及局部变量。
final修饰的类 不可以被继承,但是可以继承其他类。
final修饰的方法 不可以被子类重写。
final修饰的变量 称为常量,不会改变的值。
如果final修饰的变量是基本类型,那么变量存储的数据值不能发生改变。
如果final西施的变量是引用类型,那么变量存储的地址值是不能改变的,但是地址指向的对象内容是可以发生变化的。
final int age = 21;
final Student s =new Student();
s.name = "abc";
s.name = "cbd";
System.out.println(s.name); //cbd
十、 常量
常量就是使用了public static final 修饰的成员变量,必须有初始值,而且执行过程中不能改变。
命名规范:英文单词全部大写,多个单词用下划线连接起来。
常作为配置信息。
public static final String KEY = "8958530";
十一、 枚举
修饰符 enum 枚举名称{
}
public enum OrderStatus {
PENDING,
COMPUTE;
}
枚举类都是集成了枚举类型: java.lang.Enum
枚举都是最终类,不可以被继承。
构造器都是私有的,枚举对外不能创建对象。
javac OrderStatus.java 编译得到 .class文件
javap OrderStatus.class 反编译 得到如下
public final class com.OrderStatus extends java.lang.Enum<com.OrderStatus> {
public static final com.OrderStatus PENDING;
public static final com.OrderStatus COMPUTE;
public static com.OrderStatus[] values();
public static com.OrderStatus valueOf(java.lang.String);
static {};
}
十二、 抽象类
在java中abstract是抽象的意思,可以修饰类,成员方法。
public abstract 返回值类型 方法名(参数){}
抽象类不能被创建对象,因为抽象方法没有意义。
抽象类一定是个父类,如果没有子类重写他的方法,那么他将没有意义。
public abstract class Phone {
//抽象函数 没有方法体
public abstract void Call();
}
public class Iphone extends Phone{
@Override
public void Call() {
System.out.println("abstract");
}
}
final和abstract是互斥关系。
abstract定义的抽象类作为模板让子类继承,而final的类不能被继承。
抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
十三、 接口
接口是一种规范。
接口最主要的是用来解决多继承的弊端,将多继承这种机制在java中通过实现完成了。
public interface 接口名{
抽象方法1;
抽象方法2;
}
接口中的方法不能有方法体,属性必须为常量。方法可以不写public abstract
public interface Iphone{
//常量
public static final int Age = 18;
//抽象方法
public abstract void SayHi();
//public abstract可以不写
void haha();
}
实现一个接口使用关键字implements,并且实现接口的全部方法。
public class Phone implements Iphone{
@Override
public void SayHi(){
System.out.print("接口"+ this.Age);
}
}
多实现:
A implements B,C
在一个类中可以同时继承并且实现多个接口
A extends B implements C,D
JDK8之后新增方法
方法可以有方法体。
public interface AN {
default void run(){
System.out.println("wa o ");
}
}
十四、 面向对象:多态
指对象可以有多种形态。
如:你在vs中按f1出现vs的帮助文档,在idea中按f1则会出现idea的使用帮助。
同类型对象,执行同一个行为,会变现出不同的特征。
父类类型或者接口类型 变量 = new 子类的对象();
Person p1 = new Student();
p1.run(); //方法 编译看左边Person的方法,运行看右边Student的方法
Person p2 = new Teacher();
p2.run();
System.out.println(p2.name); //变量 编译看左边,运行看左边
优势
在多态形式下,右边对象可以实现解耦合,便于维护和扩展。
比如 new Student(); 可以随意改为new Teacher();而不用改下面的逻辑。
在定义方法的时候,使用父类型作为参数,该方法就可以接收父类的一切子类对象。
public static void go(Person p){
}
//使用时
Person p = new Student();
go(p);
多态下不能使用子类独有功能,编译时就会报错。
多态的三个必要条件:继承、重写、父类引用指向子类对象
类型转换
自动类型转换 子到父。
强制类型转换 父到子。
子类 对象变量 = (子类)父类型的变量
Person s = new Student(); //自动
Student stu = (Student) s; //强制
强制转换时如果不符 则会报错。
Person p = new Teacher();
Student stu = (Student) p; //报错 无法转换
在转换前使用 instanceof 判断当前对象的真实地址,再进行强制转换。
对象变量名 instanceof 真实类型
Person s =new Student();
Person p = new Teacher();
if(s instanceof Student){//true
Student stu = (Student) s; //执行
stu.stufun(); //Student子类独有方法
}
if(p instanceof Student){ //false
Student stu = (Student) p;//不会执行
stu.stufun();
}
强制转换后就可以使用子类的独有功能。
十五、 内部类
在一个类的内部定义一个类,成为内部类。
内部类可以访问外部类所有成员,哪怕是私有的。
// 外部类
public class Outer {
private String haha = "哈哈大笑";
//内部类
public class Inner{
public void HAHA(){
System.out.println(haha);
}
}
}
//访问方式 外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
Outer.Inner inner = new Outer().new Inner();
inner.HAHA();
局部内部类
方法中的内部类
public void out(){
class Inner{
public void inner(){
System.out.println("内部类方法");
}
}
Inner in = new Inner();
in.inner();
}
调用out()方法时,自动调用内部类中的方法
class People {
private int heartbeat = 150;
public class Heart {
private int heartbeat = 110;
public void show() {
int heartbeat = 78;
System.out.println(heartbeat);// 78
System.out.println(this.heartbeat);// 110
System.out.println(People.this.heartbeat);// 150. 外部类.this.变量
}
}
}
匿名内部类
本质上是一个没有名字的局部内部类,定义在方法中、代码块中。
new 类|抽象类名|接口名(){
重写方法;
}
new AN(){ //实例化接口
public void smoking(){
System.out.println("smoking");
}
}.smoking();
public abstract class Person {
public abstract void run();
}
new Person(){ //实例化抽象类 抽象方法必须实现。
@Override
public void run() {
//无需定义子类 快速实现方法
System.out.println("Student");
}
}.run();