JavaOOP
Java面向对象
2026.01.15
我好想哭吧我昨天写的没保存
算了不管了反正也没看多少(
回顾方法以及加深
不多说吧,记一下重点的东西好了
break和return的区别:
break:跳出switch,结束循环
return:结束方法,返回一个结果
方法名注意规范定义,首字母大写,见名知意
静态方法与非静态方法
//这里是另外定义的类
package com.flora.base.lovers;
//Demo01 类
public class Demo01 {
//方法
public static void say(){
System.out.println("上课不许说话");
}
public void dontsay(){
System.out.println("上课应该玩手机");
}
}
//这里是主要使用的类
package com.flora.base.lovers;
public class Demo02 {
static void main(String[] args) {
//静态方法 static
Demo01.say();
//当我们使用非静态方法时,我们就要实例化这个类
//对象类型 对象名 = 对象值
Demo01 demo=new Demo01();
demo.dontsay();
//静态方法不能调用非静态方法,但是非静态方法可以调用静态方法
}
}
静态方法不能调用非静态方法,但是非静态方法可以调用静态方法
原因:静态方法是和类一起加载的,而非静态方法是类实例化后才存在的
在静态方法中调用一个非静态方法相当于在调用一个不存在的方法
值传递与引用传递
值传递:
package com.flora.base.lovers;
public class Demo03 {
static void main(String[] args) {
int a=1;
Demo03.change(a);
System.out.println(a);//1
//值传递只是将值赋给了调用方法中的形参,本身没有变化
}
//值传递
public static void change(int a){
a=10;
//返回值为空
}
}
引用传递:
package com.flora.base.lovers;
//引用传递:对象,本质还是值传递
public class Demo04 {
static void main(String[] args) {
Student student=new Student();
System.out.println(student.name);//null
Demo04.change(student);
System.out.println(student.name);//flora2
}
public static void change(Student student){
//Student 是一个对象,指向的是Student student=new Student(),这是一个具体的人,可以改变属性
student.name="flora2";
}
}
//定义了一个Student类,有一个属性name
class Student{
String name;
}
类与对象的关系
类是一种抽象的数据类型,它是对某一类事物的整体描述或定义,但是不能代表某一个具
体的事务
而对象则是抽象概念的一个具体事例
比如说:人类是一个类,而其中一个人就是人类这个类的具体事例
注意:
一个项目应该只存在一个main方法!!!
实例:
//这是一个Classmate类
package com.flora.base.lovers;
//学生类
public class Classmate {
//属性:字段
String name;//默认null
int age;//默认0
//方法
public void study(){
System.out.println(this.name+"学生不许学习");
}
}
//这里是主类,main方法在这里
package com.flora.base.lovers;
public class Application {
static void main(String[] args) {
//类: 抽象的,我们需要将他实例化
//类实例化后会返回一个自己的对象
Classmate classmate=new Classmate();
classmate.name="sakuya";
classmate.age=18;
System.out.println(classmate.name);//sakuya
System.out.println(classmate.age);//18
}
}
构造器详解
一个类即使什么都不写,也会存在一个方法
package com.flora.base.lovers;
//学生类
public class Classmate {
String name;
//显示的定义构造器
//实例化初始值
public Classmate(){
this.name="flora";//原来的初始值是null,现在是flora
}
//构造器的作用:
//1.使用new关键字的本质是调用构造器
//2.构造器用来初始化值
//有参构造:一旦定义了有参构造,无参就必须显示定义
public Classmate(String a){
this.name="aaa";
}
//alt+insert快捷键生成构造器
}
//这里是实例应用
package com.flora.base.lovers;
public class Application {
static void main(String[] args) {
Classmate classmate=new Classmate();
System.out.println(classmate.name);//flora
Classmate mate=new Classmate("papa");
System.out.println(mate.name);//aaa
}
}
构造器 特点:和类名相同,没有返回值
作用:使用new关键字的本质是调用构造器,构造器用来初始化值
注意:
- 定义有参构造之后,如果要使用无参构造,要明确定义一个可见的无参构造
- alt+insert快捷键生成构造器
this关键字:
this在Java中主要有三个作用:
- 在代码中,当方法的参数名和类的成员变量名一样时,用this变量名就知道指的是这个类自己的成员变量,不是传进来的参数
- 在类的一个构造器里,用this()可以直接调用这个类的另外一个构造器,少写重复代码
- 对于当前这个对象的指代
创建对象内存分析
我们在创建对象时,即使都是new Pet(),但是由于Java的指针无处不在(,两个对象在内存中所指向的地址不同
诶呀反正就是堆栈内存区那些
类与对象小结
必须使用new关键字创建对象,构造器Person person=new Person();
对象的属性:person.name
对象的方法:person.sleep()
默认初始化:
数字:0 0.0
char:u0000
boolean:false
引用:null
封装
程序设计要求高内聚低耦合
***:属性私有,get/set
//这里是主程序
package com.flora.base.lovers.Demo01;
public class Main {
static void main(String[] args) {
Student s1=new Student();
//s1.name=,报错,不让用,因为name在Student类里面是私有权限
s1.setName("flora");
System.out.println(s1.getName());//flora
s1.setAge(999);
System.out.println(s1.getAge());//114514,哥们你是人类不
}
}
//这里是调用它的类
package com.flora.base.lovers.Demo01;
//关键词private,私有
public class Student {
//属性私有
private String name;
private int id;
private char sex;
private int age;
//提供一些可以操作这个属性的方法
//提供一些public的get,set方法
//get,获得这个数据
public String getName(){
return this.name;
}
//set,给这个数据设置值
public void setName(String name){
this.name=name;
}
//依旧是alt+insert快捷方式
//在Java中,由于我们对类进行了封装,因此使用get/set方式可以对外部调用输入的值进行检查或过滤
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>=0&&age<=120){
this.age = age;
}
else{
System.out.println("哥们你是人类不");
this.age=114514;
}
}
}
封装的作用:
- 可以对输入的数据进行过滤,提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 提高了系统的可维护性
继承
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
关键词extends,子类是父类的扩展
Java中类只有单继承,没有多继承!!!!
啥意思捏,一个儿子只能有一个爸爸,但是一个爸爸可以有很多个儿子(
继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合等等
子类(派生类),父类(基类),子类继承父类,使用关键字extends来表示
在Java中,所有的类都默认直接或者间接继承object类!
package com.flora.base.lovers.Demo02;
//学生 is 人:派生类,子类
public class Student extends Person{
}
package com.flora.base.lovers.Demo02;
//人 父类
public class Person {
public void say(){
System.out.println("我好困");
}
}
package com.flora.base.lovers.Demo02;
public class Appplication {
static void main(String[] args) {
Student stu1=new Student();
stu1.say();//我好困
//诶你说神不神奇呢我Student类里什么都没写为什么能用呢?
//因为Student类继承了Person类!
//子类能够继承父类的所有方法!!
//前提:权限是public权限*************
//private权限的无法继承,只能通过get/set
}
}
Super关键词
子类可以通过super关键词来访问父类的属性
super注意点:
- super是调用父类的构造方法,必须在子类构造方法语句的第一个(不显式也行,默认先执行父类构造)
- super只能出现在子类的方法或者构造方法中!!!
- super和this不能同时调用构造方法!!!
super与this的区别:
- 代表的对象不同。
this代表本身调用的对象,super代表父类对象的应用
前提条件不同。
this没有继承也可以使用,super只能在继承条件下才可以使用
构造方法不同。
this():本类的构造
super():父类的构造
方法重写
先上代码示例:
package com.flora.base.lovers.Demo;
public class A extends B{
@Override
public void test() {
System.out.println("A==test()");
}
}
package com.flora.base.lovers.Demo;
//重写都是方法的重写,和属性无关
public class B {
public void test(){
System.out.println("B==test()");
}
}
package com.flora.base.lovers.Demo;
public class AApplication {
//静态的方法和非静态的方法区别很大!
//静态方法:方法的调用只和左边定义的数据类型有关
//
static void main(String[] args) {
A a=new A();
a.test();//A
//父类的引用指向了子类
B b=new A();//子类重写了父类的方法
b.test();//A
}
}
总结:重写需要有继承关系,而且是子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大,但是不能缩小 public>Protected>Default>private
- 抛出的异常范围可以被缩小,但是不能扩大
重写,子类的方法和父类必须一致,方法体不同!
为什么需要重写:
- 父类的部分功能子类不一定需要,或者不一定满足
- alt+insert :override,重写选项
多态
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
话不多说上代码!
package com.flora.base.lovers.Demo04;
//父类
public class Person {
public void run(){
System.out.println("run");
}
}
package com.flora.base.lovers.Demo04;
//子类
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
package com.flora.base.lovers.Demo04;
public class Applicationn {
static void main(String[] args) {
//一个对象的实际类型是确定的
//但是可以指向的引用类型就不确定了:父类的引用指向子类
//Student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person父类可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,与右边关系不大!!!
s2.run();//son,子类重写了父类的方法,执行子类
//s2.eat()报错
//((Student)s2)=eat();可以进行类型转换,此时运行不报错
s1.run();//son
}
}
多态的注意事项:
- 多态是方法的多态(重写(误),属性没有多态!
- 只有存在父类和子类之间这种关系才可以进行类型转换!
- 存在条件:有继承关系,方法需要进行重写,父类引用指向子类对象!
不能进行重写的方法:
- static方法属于类,不属于实例,不能进行重写
- final 常量
- private 私有方法也不能进行重写
instanceof关键字
instanceof关键字可以判断两个类之间是否存在父子关系
工作方式:
- 先判断instanceof左右两边的类是不是存在父子关系,不是直接编译报错
- 是的话,进行下一步判断,左边的对象属不属于右边的类,是的话true,不是的话false
类型转换
package com.flora.base.lovers.Demo04;
//父类
public class Person {
public void run(){
System.out.println("run");
}
}
package com.flora.base.lovers.Demo04;
//子类
public class Student extends Person{
public void pri(){
System.out.println("儿子自己的");
}
}
package com.flora.base.lovers.Demo04;
public class Applicationn {
static void main(String[] args) {
//类型之间的转化:父类 子类
//高转低
Person obj=new Student();
//如果我们将student对象转换为Student类型,就可以使用Student类的方法了!
((Student)obj).pri();//强制转型
//子类转换为父类,可能会丢失自己本来的方法
Student student=new Student();
Person person=student;
person.run();//student子类转换为person父类,不能再使用自己独有的pri()方法
}
}
总结:
- 父类的引用指向子类的对象
- 把子类转换为父类,向上自动转型
- 把父类转换为子类,强制向下转型
- 作用:方便方法的调用,减少重复代码
Static修饰符
package com.flora.base.lovers.Demo05;
//static
public class Student {
private static int age;//静态变量
private double score;//非静态变量
static void main(String[] args) {
Student student=new Student();
System.out.println(student.score);
System.out.println(student.age);
//System.out.println(Student.score);//score不是类变量,不能通过类来调用
System.out.println(Student.age);//age有static修饰,是类变量,可以通过类来调用
}
}
方法
非静态的方法可以调用静态方法,静态方法可以调用静态方法,但是静态方法不可以调用非静态方法,如果要调用,必须先new一个类
代码块
代码块在构造器之前执行,静态代码块最先执行且永久只执行一次
代码块常被用来赋初值
**:通过final修饰的类不可以有子类
抽象类
关键字abstract
抽象类的所有方法必须要由它的子类通过重写方法来实现
抽象类的特点:
- 抽象类不能new,只能靠子类去实现它:约束!
- 抽象类中可以写普通的方法
- 抽象方法必须在抽象类中
抽象的抽象:约束!
package com.flora.base.lovers.Demo06;
public abstract class Action {
//不想自己写,有人帮咱们写
//abstract,抽象方法,没有方法的实现,只有方法的名字
public abstract void doSomething();
}
package com.flora.base.lovers.Demo06;
//子类必须要通过重写实现抽象类父类的方法,否则报错
//除非子类也是一个abstract
public class A extends Action{
@Override
public void doSomething() {
}
}
抽象类存在构造器吗?
存在。抽象类的子类继承他的时候,子类的构造器会默认调用抽象类的构造器,用来初始化抽象类里面的成员变量,跟普通类的继承逻辑是一样的。
抽象类存在的意义是什么?
给同类型的子类定好通用规则和共性功能,保证子类都能够实现这些方法,从而保证子类行为一致
接口的定义与实现
把接口与之前的普通类和抽象类作对比
普通类只有具体实现
抽象类具体实现和规范(抽象方法)都有
而接口只有规范,自己无法写方法
关键字interface
package com.flora.base.lovers.Demo07;
//接口都需要有实践类
public interface nserService {
//接口中的所有定义其实都是抽象的(public abstract)
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
//接口中的属性都是常量(public static final)
int age=99;
}
package com.flora.base.lovers.Demo07;
public interface timeService {
void time();
}
package com.flora.base.lovers.Demo07;
//类 可以通过关键字implements实现接口
//实现接口的类必须要重写接口中的方法
//接口可以实现多继承,继承的接口之间用逗号分隔
public class nserImpr implements nserService,timeService{
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void time() {
}
}
接口的作用:
- 约束
- 定义一些方法,让不同的人实现抽象方法
- 接口内的方法是抽象的,属性是常量
- 接口不能被实例化,接口中没有构造方法
- implements关键字可以实现多个接口
- 实现接口的类必须要重写接口中的方法
内部类
package com.flora.base.lovers.Demo10;
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类");
}
public class Inner{
public void in(){
System.out.println("这是内部类");
}
//内部类可以获得外部类的私有属性
public void getId(){
System.out.println(id);
}
}
}
//一个java类里可以有多个class类,但是只能有一个public class
class A{
}
package com.flora.base.lovers.Demo10;
public class Applicaation {
static void main(String[] args) {
Outer out=new Outer();
//可以通过外部类来实现内部类的实例化**
Outer.Inner inner=out.new Inner();
inner.getId();//10
inner.in();//这是内部类
}
}
内部类就是在一个类的内部再次定义一个类,内部类分为四种:
成员内部类
静态内部类:成员内部类加一个static修饰符
局部内部类:在方法内定义的类
匿名内部类:不用将实例保存到变量中直接new
浙公网安备 33010602011771号