面向对象
java内存
-
1 栈内存(Stock) 存放的都是方法中的局部变量 ,方法的运行一定要在栈中运行
局部变量:方法的参数 或者是方法{}内部的变量
作用域:一旦超出作用域 立刻从栈内存中消失 -
2 堆(heap) 凡是New出来的东西,都在堆内存当中
堆内存当中的东西都有一个地址值:16进制
如果是整数 默认为0
如果是浮点数 默认是0.0
如果是字符 默认是’\u0000’
如果是布尔 默认是false
如果是引用 默认是null -
3 方法区(Method Area) 存储.class 相关信息,包含方法的信息
-
4 本地方法栈 与操作系统有关
-
5寄存器 与cpu有关
-
对象没有赋值的时候,会有默认值,默认值和数组一样。
-
堆中的成员方法保存的是方法区的成员方法的地址值
-
当一个对象作为参数传递到方法时,实际上传递进去的是对象的地址值
-
当一个对象作为方法的返回值时,返回值其实就是对象的地址值
public static 返回值类型 方法名(参数){}
局部变量 和 成员变量
- 定义的位置不一样
局部变量 定义在方法内部
成员变量 在方法的外部,直接写在类中
- 作用范围不一样
局部变量 只有在方法中才可以使用 出了方法就不行
成员变量 整个类全部通用
- 默认值不一样
局部变量 如果没有默认值,想使用就有手动赋值
成员变量 如果么有赋值,会有默认值,规则和数组一样
- 内存的位置不一样
局部变量 位于栈内存
成员变量 位于堆内存
- 生命周期不一样
局部变量 随着方法进栈而诞生 随着方法的出栈而消失
成员变量 随着对象的创建而诞生,随着对象被垃圾回收而消失
方法的参数就是局部变量 参数在调用的时候必然会被赋值
封装继承多态
封装
定义
就是将一些细节隐藏起来,对于外界不可见
-
方法就是一种封装
perivate也是一种封装 -
private进行修饰,本类中可以随意访问 但是超出本类的就不能直接访问了
间接访问private成员变量就是 使用getter setter -
对于基本类型的boolean值,getter方法一定要写成isXxx的形式,而SetXxx规则没变
当方法的局部变量和类的成员变量重名的时候,
根据就近原则,优先使用局部变量
访问成员变量使用 this.成员变量
通过谁调用的方法,谁就是this
构造方法
定义
- 构造方法就是专门用来创建对象的方法,当我们通过new来创建对象时,就是在调用构造方法
- 构造方法的名称必须和所在类的名称完全一样,就连大小写也一样
- 构造方法不要写返回值类型 连void也不要
- 构造方法不能return一个具体的返回值
- 如果没有编写任何构造方法,那么编译器就会默认赠送一个构造方法,没有参数,方法什么
都不做 - 一旦编写了至少一个构造方法,那么编译器就不会赠送
- 构造方法也是可以重载的
标准类
- 所有的成员变量都要使用private关键字来修饰
- 为每一个成员变量编写一对Getter和Setter方法
- 编写一个无参数的构造方法
- 编写一个全参数的构造方法
一个标准的类也叫java Bean
- java API Application Programming Interface 应用程序编程接口
- java api是一本程序员的字典
引用类型的一般使用步骤
- 导包
import 包路径.类名称
只有java.lang包下的内容不需要导包,其他的包都需要导入 - 创建
类名称 对象名 = new 类名称() - 使用
对象名.方法名()
static
-
static用于成员变量时,那么这个变量不在属于自己,而是对象所属于的类,多个对象共享一份
数据 -
有satic称为静态方法,没有static称为成员方法
静态方法不属于对象而是属于类的
没有satic的方法必须先创建对象,才能使用
有了static可以直接使用 -
无论时成员方法还是成员变量,如果有了static 都推荐使用类名.方法名 调用
-
静态不能直接访非静态
原因:内存当中先有静态,后有非静态内容
先人不知道后人,但是后人知道前人 -
静态方法中不能用this
-
根据类名访问静态成员变量时,全程和对象没有关系,只和类有关系
静态代码块
public class 类名称 {
static {
//
}
}
继承
-
继承是多态的前提,没有继承,就没有多态
师父和徒弟的关系,师父会多少武功,大徒弟也会,小徒弟也会 -
继承主要解决的问题就是: 共性抽取
-
父类(超类,基类) 子类(派生类)
继承关系的特点
- 子类可以拥有父类的内容
- 子类可以拥有自己专有的内容
定义父类的格式 (一个普通类的定义)
定义子类的格式 public class 子类名称 extends 父类名称{
}
在父类的继承关系中,如果成员变量重名,则创建子类对象时,有两种访问方式
- 直接通过子类对象访问成员变量
- 等号左边是谁,就优先用谁
- 间接通过成员方法访问成员变量
- 该方法属于谁,就优先用谁,没有则向上找
局部变量 | 本类的成员变量 | 父类的成员变量 |
---|---|---|
直接写成员变量 | this.成员变量 | super.成员变量 |
在父子类的继承关系当中,创建子类对象,访问成员方法的规则
- 创建的对象是谁,就优先用谁,如果没有,则向上找
注意事项
- 无论是成员变量还是成员方法,如果每没有,都是向上找父类,绝不会向下找子类
重写
- 概念: 在继承关系当中,参数列表一样,方法名称一样
区别
-
重写 :
方法的名称一样,参数列表也一样 覆盖,覆写
-
重载
方法的名称一样,参数列表不一样
覆盖重写的特点
- 创建的是子类对象,则优先使用子类方法。
注意事项
- 必须保证父子类之间的名称相同,参数列表也相同
@override
写在方法前面,用来检测是不是有效的正确覆盖重写,这个注解就算不写,只要满足要求
就是正确的覆盖重写
-
子类方法的返回值必须小于等于父类的方法返回值范围
小扩展: java.lang.object类是所有类的公共最高父类,java.lang.String 就是object的子类
-
子类的方法权限必须大于等于父类方法的方法权限
public > protected > default > private
继承关系中,父子类构造方法的访问特点
- 子类必须调用父类构造方法,子类构造方法当中有一个默认的隐含super() 调用,所有一定是先调用
父类的构造,后执行子类的构造
-
子类构造可以通过super 关键字来调用父类重载构造
-
super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造
-
子类必须调用父类构造方法,不写赠送super() 写了则用指定的super调用,super只能有一个,还必须是第一个
super关键字有三种用法
-
在子类的成员方法中,访问父类的成员变量
-
在子类的成员方法中,访问父类的成员方法
-
在子类的构造方法中,访问父类的构造方法
this关键字的用来访问本类的内容
-
在本类的成员方法中,访问本类的成员变量
-
在本类的成员方法中,访问本类的另一个成员方法
-
类的构造方法中,访问本类的另一个构造方法
-
this调用也必须是构造方法的第一个语句,唯一一个
-
super 和this不能同时调用,不能同时使用
Java语言时是单继承的
-
一个类的直接父类只能有唯一一个
class A {} class B extends A{} //正确 class C {} class D extends A,C {} //错误
-
Java语言可以多级继承
class A {} class B extends A{} //正确 class C extends B{} //正确
-
Java.lang.object在继承中最高
-
一个子类的直接父类是唯一的,但是一个父类可以有多个 子类
抽象
- 如果父类当中的方法不确定如何进行{}方法体实现,那这就是一个抽象方法
public abstract class Animal { //抽象方法:就是加上abstrat关键字,然后去掉大括号,直接用分号结束 //抽象类: 抽象方法所在的类,必须是抽象类才行,在class之前加上abstra即可 public abstract void eat(); public void normalMethod() { } }
-
如何使用抽象类和抽象方法
- 不能直接创建new抽象类方法
- 必须用一个子类来实现抽象方法
- 子类必须覆盖重写抽象父类当中的所有抽象方法
覆盖重写 子类去掉抽象方法中的abstract 关键字,然后补上方法体大括号
- 创建子类对象进行使用
--------------------------------------------------------- public abstract class Animal { public abstract void eat(); public void normalMethod() { } } ------------------------------------------------------------ public class Cat extends Animal { @Override public void eat() { System.out.println("猫吃鱼"); } } ------------------------------------------------------------------ public class DemoMain { public static void main(String[] args) { //Animal animal = new Animal(); //错误写法 不能直接创建 Cat cat = new Cat(); cat.eat(); } }
final 关键字代表最终的,不可改变的
- 可以修饰一个类
- 可以修饰一个方法
- 还可以修饰一个局部变量
- 可以修饰一个成员变量
修饰一个类
/*
当final关键字来修饰一个类的时候,格式
public fianl class 类名 {
//...
}
含义:当前这个类不能有任何的子类,但是有父类
注意:如果一个类是final的,那么其中所有的成员方法都无法进行覆盖重写(因为没儿子)
*/
public final class MyClass {
public void method() {
System.out.println("方法执行!");
}
}
修饰一个方法
/*当方法用final关键字来修饰时,这个方法时最终方法,也就是不能被覆盖重写
对于类和方法来说,abstract和final关键字不能同时使用,引文矛盾
*/
修饰一个局部变量
public class Student {
private String name;
public Student(String name) {
this.name = name;
}
public Student() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
----------------------------------------------------------------------
public class Demo01Final {
public static void main(String[] args) {
int num1 = 10;
System.out.println(num1); //10
num1 = 20;
System.out.println(num1); //20
//一旦使用final来修饰局部变量,那么这个变量就不能进行更改
//“一次赋值,终生不变”
final int num2 = 200;
System.out.println(num2); //200
// num2 = 500; //错误写法,不能改变
// num2 = 200; //错误写法
//正确写法,只要有保证有一次赋值即可
final int num3;
num3 = 30;
//对于基本类型来说,不可变的是变量当中的数据不变
//对于引用类型来说,不可变的是变量当中的地址不变
Student stu1 = new Student();
System.out.println(stu1.getName());
stu1 = new Student("小名");
System.out.println(stu1.getName());
final Student stu2 = new Student("小花");
System.out.println(stu2.getName()); //小花
// stu2 = new Student("高原原远远"); //错误写法,fianl引用类型的变量不变,其中的地址不变
stu2.setName("小笑"); //stu2的地址值不可变,但是地址值中的内容可以改变
System.out.println(stu2.getName());//小笑
}
}
修饰一个成员变量
/*
对于成员变量来说,如果使用final关键字来修饰,那么变量也照样不可变
1 由于成员变量具有默认赠,所以用了final之后必须手动赋值,不在给你默认值
2 对于final 的成员变量,要么直接赋值,要么通过构造赋值
3 必须保证类中所有的重载的构造方法,都最终会对final成员变量就行赋值
*/
public class Person {
final private String name = "鹿晗";
}
四种权限修饰符
public >protected>default>private
权限 | public | protected | default | private |
---|---|---|---|---|
同一个类 | yes | yes | yes | yes |
同一个包 | yes | yes | yes | no |
不同包子类 | yes | yes | no | no |
不同包非子类 | yes | no | no | no |