面向对象
面向对象
面向对象(OOP)的本质就是以类的方式组织代码,以对象的组织(封装)数据
类是一种抽象的数据类型,它是对某一类事物整体的描述/定义,但不能代表某一个具体的事物
对象是抽象概念的具体实例
package com.oop.demo01;
import java.io.IOException;
/**
* @description 方法的定义:修饰符 返回类型 break跳出switch,结束循环 return是结束方法 方法名:见名知意命名要规范
* 参数列表:(参数类型 参数名) (参数类型... 参数名) 异常抛出
* @author kjy06123
* @date 2025/4/1 22:51
*/
// Demo01 类
public class Demo01 {
// main 方法
public static void main(String[] args) {}
/*
修饰符 返回值 方法名(...){
//方法体
return 返回值;
}
*/
// return 结束方法,返回一个结果
public String sayHello() {
return "Hello";
}
public void print() {
return;
}
public int max(int a, int b) {
return a > b ? a : b;//三元运算符
}
//数组下标越界:Arrayindexoutofbounds
public void readFile(String file)throws IOException{
}
}
package com.oop.demo01;
/**
* @description 方法的调用 递归调用 静态方法 非静态方法 形参和实参 值传递和引用传递 this关键字
* @author kjy06123
* @date 2025/4/1 23:04
*/
public class Demo02 {
public static void main(String[] args){
//实例化这个类 new
//对象类型 对象名 = 对象值;
Student student = new Student();
student.say();
}
// static和类一起加载的
public static void a(){
// b();
}
//类实例化后才存在的
public void b(){
}
}
package com.oop.demo01;
/**
* @description
* @author kjy06123
* @date 2025/4/1 23:21
*/
public class Demo03 {
public static void main(String[] args){
//实际参数和形式参数的类型要对应
int add = Demo03.add(1, 2);
System.out.println(add);
}
public static int add(int a,int b){
return a + b;
}
}
package com.oop.demo01;
/**
* @description 值传递
* @author kjy06123
* @date 2025/4/1 23:30
*/
public class Demo04 {
public static void main(String[] args){
int a = 1;
System.out.println(a);
Demo04.change(a);
System.out.println(a);
}
public static void change(int a){
a = 10;
}
}
package com.oop.demo01;
/**
* @description 引用传递:传递对象,本质还是值传递
* @author kjy06123
* @date 2025/4/1 23:34
*/
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);
Demo05.change(person);
System.out.println(person.name);
}
public static void change(Person person) {
// person是一个对象指向的是Person person = new Person();这是一个具体的人,可以改变属性
person.name = "kjy06123";
}
}
// 定义一个Person类,属性为name
class Person {
String name;
}
package com.oop.demo02;
/**
* @description
* @author kjy06123
* @date 2025/4/2 23:07
*/
// 在out文件中查看源码
public class Person {
// 一个类即使什么都不写,它也会存在一个方法叫做构造器或者构造方法:public Person(){}
String name;
// 构造器:
// 1.使用new关键字,本质是在调用构造器
// 2.用来初始化值
public Person() {
this.name = "kjy06123";
}
// 有参构造器:一旦定义了有参构造器,无参构造器必须显示定义
public Person(String name) {
this.name = name;
}
// 使用alt + insert 选择Constructor可以快速创建构造器
}
/*
public static void main(String[] args) {
// new:实例化了一个对象
Person person = new Person();
System.out.println(person.name); // null
// 总结
// 构造器:
// 1.和类名相同
// 2.没有返回值
// 作用:
// 1.new 本质就是调用构造方法
// 2.初始化对象的值
// 注意点:
// 1.定义有参构造器之后,如果想使用无参构造器,就得构造一个显示的无参构造器
// alt + Insert
// this. XX(表示当前类)=XX(参数传进来的值)
}
*/
封装
高内聚,低耦合
高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
数据的隐藏:通常禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问
属性私有 get/set
package com.oop.demo04;
/**
* @description
* @author kjy06123
* @date 2025/4/18 17:08
*/
public class Student {
// 属性私有
private String name;
private int id;
private char sex;
private int age;
// 提供一些可以操作这个属性的方法 ,public 的get和set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0 || age > 120) {
this.age = 3;
} else {
this.age = age;
}
}
}
/*
public static void main(String[] args){
Student s1 = new Student();
s1.setName("kjy");
System.out.println(s1.getName());
s1.setAge(-1);
System.out.println(s1.getAge());
}
*/
/*
1. 提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一接口
4.系统可维护性增加了
*/
继承
本质是对某一批类的抽象,从而实现对现实世界更好的建模
extends :扩展
java中类只有单继承,没有多继承!
继承是类和类之间的一种关系。类与类之间的关系还有依赖、组合、聚合等。
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
Vs this:
代表的对象不同:
this:本身调用这个对象
super:代表父类对象的引用
前提
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法
this()本类的构造
super()父类的构造
重写:需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小: Public>Protected>Default>Private
- 抛出的异常:范围可以被缩小,但不能扩大
重写子类的方法和父类必须要一致,方法体不同
为什么需要重写:
1. 父类的功能,子类不一定需要,或者不一定满足
1. Alt + Insert override;
多态
多态是方法的多态,属性没有多态
父类和子类有联系 不然会出现类型转换异常如ClassCastException
存在条件:继承关系,方法需要重写,父类引用指向子类对象 Father f1 = new Son();
不能重写的有:
- static 方法 属于类,不属于实例
- final 常量
- private 方法
instanceof (类型类型)引用类型,判断一个对象是什么类型
父类引用指向子类的对象
子类转换成父类,向上转型
父类转换成子类,向下转型:强制转换
方便方法的调用,减少重复的代码简洁
//static只会在类加载时运行一次
public class Person {
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args){
Person person = new Person();
System.out.println("================");
Person person1 = new Person();
}
}
import static java.lang.Math.random;
/**
* @description
* @author kjy06123
* @date 2025/4/20 20:57
*/
public class Test {
public static void main(String[] args){
System.out.println(random());
}
}
抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将声明为抽象方法,那么这个类就是抽象类
package com.oop.demo08;
/**
* @description abstract 抽象类
* @author kjy06123
* @date 2025/4/20 21:41
*/
public abstract class Action {
//抽象方法只有方法名,没有方法的实现
public abstract void doSomething();
//不能new 只能靠子类来去实现
//抽象类中可以写普通的方法
//抽象方法必须在抽象类中
}
package com.oop.demo08;
/**
* @description
* @author kjy06123
* @date 2025/4/20 21:44
*/
//extends 是单继承的 接口是可以多继承
//抽象类的方法,必须由继承他的子类来实现方法重写 除非子类也是抽象的
public class A extends Action{
@Override
public void doSomething() {
}
}
接口
接口就是给出一些没有实现的方法,封装到一起,到某个类需要使用时根据具体情况在把方法实现出来
语法:
interface 接口名{
//属性
//方法(1抽象方法 2默认实现方法(default)3静态方法(static)))
}
class 类名 implements 接口{
自己属性
自己方法
必须要实现接口的抽象方法
}
细节:
- 接口不能被实例化
- 接口的所有方法都是public,接口中抽象方法可以不用abstract修饰
- 一个普通类实现接口,必须将该接口所有方法都实现
- 抽象类实现接口,可以不用实现接口方法 class abstract A implements IA{}
- 一个类同时可以实现多个接口 class C implements A,B{}
- 接口中的属性都是public static final修饰的比如 int a =1;实际上是public static final int a =1;
- 接口中属性的访问形式:接口名.属性名
- 接口不能继承其他类,但是可以继承多个别的接口 interface A extends B,C{}
- 接口的修饰符只能是public和默认这个和类的修饰符一样 public interface AI {}||interface AI {}
接口在一定程度上实现代码解耦(接口规范性+动态绑定机制)
接口的多态性
-
多态参数
package com.kjy06123.interface_; /** * @description 多态参数 * @author kjy06123 * @date 2025/4/25 0:37 */ public class InterfacePolyParameter { public static void main(String[] args) { // 接口的多态体现 // 接口类型的变量if01可以指向实现了IF接口类的对象实例 IF if01 = new Monster(); if01 = new Car(); // 继承体现的多态 // 父类类型的变量a可以指向继承AAA的子类的对象实例 AAA a = new BBB(); a = new CCC(); } } interface IF {} class Monster implements IF {} class Car implements IF {} class AAA {} class BBB extends AAA {} class CCC extends AAA {} -
多态数组
package com.kjy06123.interface_; /** * @description 多态数组 * @author kjy06123 * @date 2025/4/25 0:43 */ public class InterfacePolyArr { public static void main(String[] args){ Usb[] usbs = new Usb[2]; usbs[0] = new Phone_(); usbs[1] = new Camera_(); for(int i = 0; i < usbs.length; i++) { usbs[i].work(); if (usbs[i] instanceof Phone_){ ((Phone_) usbs[i]).call(); } } } } interface Usb{ void work(); } class Phone_ implements Usb{ public void call(){ System.out.println("Phone calling"); } @Override public void work() { System.out.println("Phone working"); } } class Camera_ implements Usb{ @Override public void work() { System.out.println("camera working"); } } -
接口存在多态传递
package com.kjy06123.interface_; /** * @description 多态传递现象 * @author kjy06123 * @date 2025/4/25 0:55 */ public class InterfacePolyPass { public static void main(String[] args){ IG ig = new Teacher(); IH ih = new Teacher(); } } interface IH{} interface IG extends IH{} class Teacher implements IG{}
内部类
局部内部类
package com.kjy06123.innerclass;
/**
* @description 局部内部类的使用
* @author kjy06123
* @date 2025/4/25 20:29
*/
public class LocalInnerClass {
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.m1();
}
}
class Outer02 {//外部类
private int n1 = 100;
private void m2() {
System.out.println("Outer02 m2()");
}
public void m1() {
// 1.局部内部类是定义在外部类的局部位置,通常在方法
// 3.不能添加访问修饰符,但是可以使用final修饰
// 4.作用域:仅仅在定义它的方法或代码块中
final class Inner02 {//局部内部类(本质还是一个类)
// 2.可以直接访问外部类的所有成员,包含私有的
public void f1() {
// 5.局部内部类可以直接访问外部类的成员,比如下面 外部类n1 和m2()
System.out.println("n1=" + n1);
m2();
}
}
// 6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
//局部内部类定义在方法中或代码块
//作用域在方法体或者代码块中
//本质还是一个类
匿名内部类
package com.kjy06123.innerclass;
/**
* @description 匿名内部类
* @author kjy06123
* @date 2025/4/25 21:13
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04 {
private int n1 = 10;
public void method() {
// 基于接口的匿名内部类
// 1.需求:想使用IA接口,并创建对象
// 2.传统方式,写一个类,实现该接口,并创建对象
// IA tiger = new Tiger();//传统方式
// tiger.cry();
// 3.需求:Tiger类只使用一次,后面不再使用
// 4.使用匿名内部类来简化开发
// 5.tiger的编译类型是IA 运行类型就是匿名内部类(Outer04$1)
/* 底层会分配 类名 Outer04$1
class Outer04$1 implements IA{
@Override
public void cry() {
System.out.println("Tiger 叫唤");
}
}
}
*/
// 6.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了Outer04$1实例,并把地址
// 返回给tiger
// 7.匿名内部类使用一次,就不能再使用了
IA tiger =
new IA() {
@Override
public void cry() {
System.out.println("Tiger 叫唤");
}
};
System.out.println("tiger的运行类型=" + tiger.getClass()); // Outer04$1
tiger.cry();
// 分析基于接口的匿名内部类
// 1.father编译类型是Father
// 2.运行类型是Outer04$2
// 3.底层会创建匿名内部类
/*
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
}
*/
//4.同时也直接返回了匿名内部类 Outer04$2的对象
//5.(jack)参数列表会传递给 构造器
Father father =
new Father("jack") {
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father对象的运行类型=" + father.getClass()); // Outer04$2
father.test();
// 基于抽象类的匿名内部类
Animal animal =
new Animal() {
@Override
void eat() {
System.out.println("dog");
}
};
animal.eat();
}
}
interface IA {
public void cry();
}
// class Tiger implements IA{//传统方式
// @Override
// public void cry() {
// System.out.println("Tiger 叫唤");
// }
// }
class Father {
public Father(String name) {
System.out.println("接收到name="+name);
}
public void test() {}
}
abstract class Animal{
abstract void eat();
}
package com.kjy06123.innerclass;
/**
* @description
* @author kjy06123
* @date 2025/4/25 23:32
*/
public class AnonymousInnerClassDetail {
public static void main(String[] args){
Outer05 outer05 = new Outer05();
outer05.f1();
//外部其他类 不能访问匿名内部类
System.out.println("main Outer05 hashcode="+outer05);
}
}
class Outer05{
private int n1 = 99;
public void f1(){
// 不能添加访问修饰符,因为它的地位就是一个局部变量
// 作用域:仅仅在定义它的方法或代码块中
Person person =
new Person() {
private int n1 = 88;
@Override
public void hi() {
// 可以直接访问外部类的所有成员,包含私有的
// 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,
// 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问
System.out.println("匿名内部类重写了hi方法 n1=" + n1 + "外部类的n1=" + Outer05.this.n1);
System.out.println("Outer05.this hashcode="+Outer05.this);
}
};
person.hi();
new Person() {
@Override
public void hi() {
System.out.println("匿名内部类重写了hi方法 哈哈哈");
}
@Override
public void ok(String str) {
super.ok(str);
}
}.ok("jack");
}
}
class Person{
public void hi(){
System.out.println("Person hi()");
}
public void ok(String str){
System.out.println("Person ok()"+ str);
}
}
匿名内部类的最佳实践
package com.kjy06123.innerclass;
/**
* @description 匿名内部类的最佳实践
* @author kjy06123
* @date 2025/4/26 0:34
*/
public class InnerClassExercise {
public static void main(String[] args) {
// 当做实参直接传递,简洁高效
f1(
new IL() {
@Override
public void show() {
System.out.println("hello");
}
});
//传统方法
f1(new Picture());
}
// 静态方法,形参是接口类型
public static void f1(IL il) {
il.show();
}
}
interface IL {
void show();
}
// 类->实现 IL => 编程领域 (硬编码)
class Picture implements IL {
@Override
public void show() {
System.out.println("这是一副名画 XX...");
}
}
成员内部类
package com.kjy06123.innerclass;
/**
* @description 成员内部类
* @author kjy06123
* @date 2025/4/26 15:46
*/
public class MemberInnerClass {
public static void main(String[] args) {
Outer08 outer08 = new Outer08();
outer08.t1();
//外部其他类,使用成员内部类的三种方式
//第一种
//outer08.new Inner08();相当于把 new Inner08()当做outer08成员
Outer08.Inner08 inner08 = outer08.new Inner08();
inner08.say();
//第二种在外部类中,编写一个方法返回Inner08duixiang
Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
inner08Instance.say();
}
}
class Outer08 { // 外部类
private int n1 = 10;
public String name = "张三";
private void hi(){
System.out.println("hi()");
}
//1.注意:成员内部类,是定义在外部类的成员位置上
//2.可以添加任意访问修饰符(public protected 默认 private),因为它的地位就是一个成员
class Inner08 { // 成员内部类
public double sal = 998;
private int n1 = 666;
public void say() {
// 可以直接访问外部类的所有成员,包含私有的
//如果成员内部类的成员和外部类的成员重名,就会遵守就近原则
//可以通过 外部类名.this.属性 来访问外部类的成员
System.out.println("n1=" + n1 + "name=" + name +"外部类的n1="+Outer08.this.n1);
hi();
}
}
//写一个方法,返回Inner08实例
public Inner08 getInner08Instance(){
return new Inner08();
}
// 写方法
public void t1() {
// 使用成员内部类
// 创建成员内部类的对象,然后使用相关的方法
Inner08 inner08 = new Inner08();
inner08.say();
System.out.println(inner08.sal);
}
}
静态内部类
package com.kjy06123.innerclass;
/**
* @description 静态内部类
* @author kjy06123
* @date 2025/4/26 21:06
*/
public class StaticInnerClass {
public static void main(String[] args) {
Outer10 outer10 = new Outer10();
outer10.m1();
// 外部其他类 使用静态内部类
// 方式 1
// 因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
Outer10.Inner10 inner10 = new Outer10.Inner10();
inner10.say();
// 方式 2
// 编写一个方法,可以返回静态内部类的对象实例. Outer10.Inner10 inner101 = outer10.getInner10();
System.out.println("============");
inner10.say();
Outer10.Inner10 inner10_ = Outer10.getInner10_();
System.out.println("************");
inner10_.say();
}
}
class Outer10 { // 外部类
private int n1 = 10;
private static String name = "张三";
private static void cry() {}
// Inner10 就是静态内部类
// 1. 放在外部类的成员位置
// 2. 使用 static 修饰
// 3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
// 4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
// 5. 作用域 :同其他的成员,为整个类体
static class Inner10 {
private static String name = "jack";
public void say() {
// 如果外部类和静态内部类的成员重名时,静态内部类访问的时,
// 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)
System.out.println(name + " 外部类 name= " + Outer10.name);
cry();
}
}
public void m1() { // 外部类---访问------>静态内部类 访问方式:创建对象,再访问
Inner10 inner10 = new Inner10();
inner10.say();
}
public Inner10 getInner10() {
return new Inner10();
}
public static Inner10 getInner10_() {
return new Inner10();
}
}

浙公网安备 33010602011771号