面向对象
对象类型 对象名 =对象值
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统.但是,具体到微观操作,仍然需要面向过程的思路去处理.
本质 以类的方式组织代码,以对象组织封装
三大特性
封装
继承
多态
认知角度先有对象 再有类 对象 对象是具体的事物 类是抽象是对对象的抽象
代码运行角度先有类 后有对象 类是对象的模板
package 面向对象;
//类
public class {
public static void sa(){
System.out.println("你爹说话了");
}
public void sb(){
System.out.println("我你爹");
}
}
xs01 zhangsan = new xs01(); //创建对象:“Zhangshan”
zhangsan.sb(); //对象行为:对象自己发出行为
修饰符
public 公共
protected 受保护的
private 私有
default 默认
静态方法 与非静态方法
对象类型 对象名 =对象值
package 面向对象;
import java.util.Scanner;
public class demo02 {
//静态方法 static
public static void main(String[] args) {
xs01.sa();
//非静态
// 实例化这个类
new xs01().sb();
xs01 xs01 = new xs01();
// 对象类型 对象名 =对象值
xs01.sb();
}
}
值传递
public class Demon05 {
public static void main(String[] args) {
int a=1;
//值传递
System.out.println(a);//1
Demon05 demon05 = new Demon05();
demon05.o(a);
System.out.println(a);//1
}public void o(int a){
a=23;
}
}
引用传递
public static void main(String[] args) {
// 引用传递
a1 a1 = new a1();
System.out.println(a1.name);//null
Demon04 demon04 = new Demon04();
demon04.a(a1);
System.out.println(a1.name);
a1.name="很坏";
System.out.println(a1.name);
}
public void a(a1 b){
// b是一个对象,指向的————👉 a1 a1 = new a1();是一个具体的人,可以改变属性
b.name="钰钰";
}
}
class a1 {
//类 类名a1
String name;
//属性name
}
类是一种抽象的数据类型 它是对某一类事物整体 描述/定义,但是并不能代表某一个具体的事物
动物 手机
对象是概念的具体实例
钰钰是人 张三是狗
创建对象
使用new 关键字创建对象
会给对象分配一些默认的值与空间 以及对类中的结构器的调用
Demo01类
package 面向对象.Demon02;
public class Demon01 {
String name;
int a;//属性 ;字段
//方法
public void xs(){ //this 代表着当前这个类
System.out.println(this.name+"学生在学习");
}
}
package 面向对象.Demon02;
//一个项目只有一个main方法
public class app {
public static void main(String[] args) {
//类 抽象的 实例化
//类实例化会返回一个自己的对象
// dx对象是Demon类的具体实例
Demon01 dx = new Demon01();
System.out.println(dx.name);//name 默认是null
dx.name="王晨狗贼";
System.out.println(dx.name);
System.out.println(dx.a);//a 默认0
dx.a=3;
System.out.println(dx.a);//3
Demon01 ds = new Demon01();
System.out.println(ds.name);//null
System.out.println(ds.a);//0
}
}
结构器
类中构造器 也称为构造方法 是在进行创建对象的时候必须调用的 并且构造器 有以下俩特点
必须 和类的名字相同
必须没有返回类型 也不能写void
package 面向对象.Demon02;
public class Demon02 {
String name;
//一个类什么都不写 它也会存在一个方法
// 显示定义构造器
// 显示化初始值
// 使用new关键字 必须要有关键字 本质是在调用构造器
int a;
public Demon02() {
}
//快捷键 alt +ins
//有参构造 一但定义了有参构造无参必须显示定义
public Demon02(String name) {
this.name = name;
}
public Demon02(int a) {
this.a = a;
}
public Demon02(String name, int a) {
this.name = name;
this.a = a;
}
}
//package 面向对象.Demon02;
//
一个项目只有一个main方法
//public class app {
// public static void main(String[] args) {
// //new 实例化了一个对象
// Demon02 ds = new Demon02(); null
// System.out.println(ds.name);
// Demon02 dx = new Demon02("牛逼");
// System.out.println(dx.name); 牛逼
//
// }
//}
构造器
和类名相同
没有返回值
作用
new 的本质是调用构造方法
初始化对象的值(初始化成员变量的值)
注意点
定义了有参构造之后 如果向使用无参构造 需要显示一个无参构造
内存分析
pet p = new pet();
pet p; 栈
p = new pet();堆
类与对象的小结
-
类于对象
类是一个模块:抽象,对象是一个具体的实例
-
方法
定义,调用
-
对应的引用
引用类型: 基本类型(8)除了八大类型 的都可以叫引用类型
对象是通过引用来操作的:栈——👉堆(地址)
-
属性:字段field 成员变量
默认初始化:
数字:0
char:u000
bolean:false
应用:nulll
修饰符 :属性类型 属性名 =属性值
-
对象的创建和使用
必须使用new 关键字创建对象 ,构造器 快捷键Alt+ins
pet p = new pet();
对象的属性 p.name
对象的方法 p.et()
-
类
静态的属性 属性
动态的行为 方法
类的初始化顺序
父类的静态字段——>父类静态代码块——>子类静态字段——>子类静态代码块——>
父类成员变量(非静态字段)——>父类非静态代码块——>父类构造器——>子类成员变量——>子类非静态代码块——>子类构造器
封装
高内聚,低藕合
高内聚就是类的内部数据操作细节自己完成,不允许外部干涉
低藕合仅暴露少量方法给外部使用
this.属性名称
指的是访问类中的成员变量,用来区分成员变量和局部变量**(重名问题)**
private int mon= 1_000;
public void setMon(int on) {
mon = on;
}
//————————————————————————————————————————
public void seMon(int mon) {
this.mon = mon;
}
属性稀有 get/set
alt+insert 快捷键 自动生成 set 还在get
get 获得这个属性
set给这数据赋值
优点
1.提供程序的安全性.保护数据
2.隐藏代码的细节
3.统一接口
4.提高了系统的可维护信
package 面向对象.封装;
public class Add01 {
public static void main(String[] args) {
Student d = new Student();
d.id=23;
System.out.println(d.id);
d.setName("吴彦祖");
System.out.println(d.getName());
d.setNl(90);
System.out.println(d.getNl());
}
}
//---------------
//类
package 面向对象.封装;
//类 private 私有
public class Student {
//学号
public int id;
// 名字
private String name;
// 性别
private char xb;
// 年龄
private int nl;
//提供一些可以操作这个属性的方法
// 提供一些public的get,set方法
// get 获得这个属性
// set给这数据赋值
// get获得这个值
public String getName() {
return this.name;
}
// set 设置值
public void setName(String name) {
this.name=name;
}
//alt+insert 快捷键 自动生成 set 还在get
public int getNl() {
return nl;
}
public void setNl(int nl) {
if (nl>100||nl<0){//不合法
this.nl = 0;
}else {
this.nl = nl;
}
}
}
继承 extends
JAVA中类只有单继承,没有多继承! 一个儿子只能有一个爸爸
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。
子类和父类之间,从意义上讲应该具有**“is a”**的关系.
在同一个包里私有的东西继承 无法访问
不在同一个 包里私有和默认的 无法访问final是断子绝孙修饰符(常量) 也无法继承**
快捷键 Ctrl+h 继承树
在Java 中所有的类,都默认直接或者间接继承object
package 面向对象.继承;
//人 父类
public class Person {
public void say(){
System.out.println("说了一句话");
}
private int mon= 1_000;
public int getMon() {
return mon;
}
public void setMon(int mon) {
this.mon = mon;
}
}
/-------------------------继承--------------------
package 面向对象.继承;
//老师 is 人 子类
//子类继承父类就会拥有父类的全部方法
public class teachar extends Person{
}
//------------------------main------------------
package 面向对象.继承.app;
import 面向对象.继承.Person;
import 面向对象.继承.Student;
import 面向对象.继承.teachar;
public class app {
public static void main(String[] args) {
teachar person = new teachar();
person.say();
System.out.println(person.getMon());
person.setMon(233);
System.out.println(person.getMon());
}
}
先父及子,静态先行
Person静态代码块—>Student静态代码块—>Person{}、Person构造器—>Student{}、Student构造器
package 面向对象.继承.继承1;
//人 父类
public class per {
protected String name="chenshuyu";
public per(){
System.out.println("per 的无参构造器执行");
}
public void pr(){
System.out.println("陈淑钰非常的帅“父类方法”");
}
}
//---------------------子---------------
package 面向对象.继承.继承1;
//学生 is 人 子类
public class St extends per {
public String name = "yuan";
public St() {
// 隐藏了一个代码 super()执行了父类的无参构造器
//写 super() 调用父类构造器,比心在子类构造器的第一行
// super();
this("大大"); // 调用有参构造器,比心在构造器函数第一行
System.out.println("St 的无参构造器执行");
}
public St(String name) {
System.out.println("2" + name);
}
public void pr() {
System.out.println("陈淑钰非常的帅“类中”");
}
public void test() {
pr();
this.pr();
super.pr();
}
public void test(String name) {
System.out.println(name);//方法里的
System.out.println(this.name);//当前类里的
System.out.println(super.name);//父类
}
}
//----------------启动----------------
package 面向对象.继承.继承1;
public class app1 {
public static void main(String[] args) {
St st = new St();
St st1 = new St("666");
System.out.println(st1.name);
}
}
//---------------------结果----------
//per 的无参构造器执行
//2大大
//St 的无参构造器执行
///per 的无参构造器执行
//2666
//yuan
super vs this
super注意点: (父类的)
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中!
- super和 this 不能同时调用构造方法!
vs this:(当前类)
代表的对象不同:
this:本身调用者这个对象super:代表父类对象的应用前提
this:没继承也可以使用
super:只能在继承条件才可以使用构造方法
this();本类的构造super():父类的构造!
方法重写
static
静态方法和非静态方法的区别
1.生命周期不同。静态方法的生命周期跟相应的类一样长,静态方法和静态数据成员会随着类的定义而被分配和装载入内存中。一直到线程结束,静态属性和方法才会被销毁。(类创建的是时候 静态方法也创建了 销毁是一起销毁的 这俩是捆绑的 一条船上的蚂蚱)
非静态方法的生命周期和类的实例化对象一样长,只有当类实例化了一个对象,非静态方法才会被创建,而当这个对象被销毁时,非静态方法也马上被销毁。
(对象创建的是时候 非静态方法也创建了 销毁是一起销毁的 这俩也是是捆绑的 一条船上的蚂蚱)
2.调用方式。静态方法可以直接调用,类名调用和对象调用。但是非静态方法只能通过对象调用。
package 面向对象.静态;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class App {
static int a;
private int b;
public static void jt(){
System.out.println("静态");
}
public void fjt(){
System.out.println("非静态");
}
public static void main(String[] args) {
App a1 = new App();
System.out.println(a1.a);
System.out.println(App.a);//静态类名直接调用
System.out.println(a1.b);
//调用方法
new App().fjt();//非静态new
App app = new App();
App.jt();//静态类名直接调用
}
}
静态代码块
作用可以赋初始值
第一个执行 只是执行一次
package 面向对象.重写.类型转换;
public class Person {
{//第2个
System.out.println("代码块");
}
static {//第一个执行 只是执行一次 作用可以赋初始值
System.out.println("静态代码块");
}
public Person() {//第3个
System.out.println("构造器");
}
public static void main(String[] args) {
Person person = new Person();
System.out.println("---------------------");
Person person2 = new Person();
}
}
重写
为什么需要重写 父类的功能 子类不一定需要 或者不一定满足
重写 :需要有继承关系 子类重写 父类的方法(不是属性)!
1.方法名必须相同
2**.参数列表必须相同** (不然就是重载了)
3.修饰符:范围可以扩大但是不能缩水:public 公共>protected 受保护的>default 默认>private 私有
4.抛出的异常:范围 可以被缩小。但不能被扩大
重写 子类的方法和父类必须一致:方法体不同
package 面向对象.重写;
//启动
public class app {
public static void main(String[] args) {
// 动态方法的调用之和左边,定义的数据集类型有关
// 静态方法调用只和左边定义的有关
// 非静态方法 重写
A a = new A();
a.test();//动态 A=>tese
//静态 A=>tese
B b = new A();
// 动态 父类的引用指向了A
b.test();// 动态 B=>tese
/*静态 A=>tese
即b是A new出来的对象,因此调用了A的方法
因为静态方法是类的方法,而非静态是对象的方法
有static时,b调用了B类的方法,因为b是用b类定义的
没有static时,b调用的是对象的方法,而b是用A类new的
静态属于类 非静态属于对象*/
}
}
//----------------------父类-----------
package 面向对象.重写;
public class B{
public void test(){
System.out.println("B=>tese");
}
}
//-----------子类----------------------
package 面向对象.重写;
//重写都是方法的重写和属性无关
public class A extends B {
@Override//注解 有功能的注解
//Override 重写
//静态方法 有 static 的方法
public void test() {
System.out.println("A=>tese");
}
}
多态
父类 对象名=new 子类;
即同一方法可以根据发送对象的不同而采用多种不同的行为方式。
(同一个引用类型 使用不同的实例而执行不同的操作)
三要素
具有 继承关系 的父类和子类
子类 重写父类 方法
使用父类的引用指向子类的对象
实现多太的两种方式
使用父类作为 形参实现多太(传递的是父类或子类对象)
使用父类作为方法返回值实现多态(返回的是父类或者子类对象)
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
方法的多态性:重载与覆写
|-重载:同一个方法名称,根据不同的参数类型及个数可以完成不同的功能。
|-覆写:同一个方法,根据操作的子类不同,所完成的功能也不同。
注意事项
多态是方法的多态 属性没有多态
父类和子类有联系 (类型转换异常!ClassCastException!)
存在的条件:继承关系 方法需要重写 父类引用指向子类(父类 a1=new 子类)
不能多态的
static 方法 属于类 不属于实例
final 是常量 无法继承:
private 方法 无法继承:
静态方法是类的方法,而非静态是对象的方法
多态的访问方式:
(1)成员变量
编译看左边,运行看左边
变量是没有重写的是类独有的
(2)成员方法
编译看左边,运行看右边
非静态的方法是对象的方法 通过对象调用
(3)静态方法
编译看左边,运行看左边
总结 静态方法是类的方法,而非静态是对象的方法
(1)成员变量
编译看左边,运行看左边
package com.itheima;
/**
* @author 11137_yyss3t3
* 多态的成员特点:
* 成员变量:编译看左边,运行看左边
* 成员方法
* 静态方法
*
*/
public class Demo1_2 {
public static void main(String[] args) {
Dad dad = new Kid();
System.out.println(dad.num);
}
}
class Dad{
int num = 20;
}
class Kid extends Dad{
int num = 10;
}
输出结果为:20
父类引用指向子类对象,父亲类和儿子类中都有成员变量,变量不像方法一样有重写,变量是没有重写的概念的,所以运行的是父类方法的成员变量。如果父类中没有这个成员变量,程序会出现编译错误。
(2)成员方法
编译看左边,运行看右边
package com.itheima;
/**
* @author 11137_yyss3t3
* 多态的成员特点:
* 成员变量
* 成员方法:编译看左边,运行看右边
* 静态方法
*
*/
public class Demo1_2 {
public static void main(String[] args) {
//父类引用指向子类对象
Dad dad = new Kid();
dad.method();
}
}
class Dad{
public void method() {
System.out.println("我是父类方法");
}
}
class Kid extends Dad{
public void method() {
System.out.println("我是子类方法");
}
}
输出的结果为:我是子类方法
因为成员方法是可以重写的,所以会执行子类的方法。但是如果父类中没有method()方法,编译器会报错。
(3)静态方法
编译看左边,运行看左边
package com.itheima;
/**
* @author 11137_yyss3t3
* 多态的成员特点:
* 成员变量
* 成员方法
* 静态方法:编译看左边,运行看左边
*
*/
public class Demo1_2 {
public static void main(String[] args) {
//父类引用指向子类对象
Dad dad = new Kid();
dad.method();
}
}
class Dad{
public static void method() {
System.out.println("我是父类静态方法");
}
}
class Kid extends Dad{
public static void method() {
System.out.println("我是子类静态方法");
}
}
输出结果是:我是父类静态方法
分析:使用变量去调用静态方法,其实相当于变量类型的类名去调用,也就是Dad.method(),所以运行的是父类里面的静态方法。如果父类没有静态方法,编译报错。
package 面向对象.多态;
public class app {
public static void main(String[] args) {
// 对象的实际类型是确定的
// new Student();
// new Person();
// 可以指向的引用类型是不确定的:父亲的引用指向子类
// Student 调用的方法都是自己的或者是继承的
Student student = new Student();
Person student1 = new Student();//父类
//person 可以指向子类 .但是不能调用子类读独有的方法
Object student2 = new Student(); //Object 祖宗类
// 对象能执行那些方法.主要看对象左边的类型 和右边关系不大
student1.run();//子类重写了父类的方法 执行子类的方法
student.run();
}
}
//-------------------父--------------
package 面向对象.多态;
public class Person {
public void run(){
System.out.println("run");
}
}
//--------------------子-------------------
package 面向对象.多态;
public class Student extends Person {
public void run(){
System.out.println("son");
}
}
instanceof
instanceof(类型转换)引用类型
(类型转换)引用类型)实例
System.out.println(X instanceof Y) 判断 x与y是否有父子关系 如果有则为 true 如果没有则为false
package 面向对象.重写.Instanceof;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import java.util.Scanner;
public class App {
public static void main(String[] args) {
// Object> Person> Student
//Object> Person> Teacher
//Object> String
Object Object1 = new Student();
//System.out.println(X instanceof Y) 判断 x与y是否有父子关系 如果有则为 true 如果没有则为false
System.out.println(Object1 instanceof Student);//true
System.out.println(Object1 instanceof Person);//true
System.out.println(Object1 instanceof Object);//true
System.out.println(Object1 instanceof Teacher);//false Object> Person> Teacher
System.out.println(Object1 instanceof String);//false Object> String
System.out.println("----------------------------");
Person Person1 = new Student();
System.out.println(Person1 instanceof Student);//true
System.out.println(Person1 instanceof Person);//true
System.out.println(Person1 instanceof Object);//true
System.out.println(Person1 instanceof Teacher);//false
/* System.out.println(Person1 instanceof String);
编译就报错
*/
}
}
类型之间的转化:基本类型转换
父子类对象的转换。
向上转型:子类对象变为父类对象,格式:父类 父类对象 = 子类实例,自动;
向下转型:父类对象变为子类对象,格式:子类 子类对象 = (子类)父类实例,强制。
方便方法调用 建设重复的代码
基本类型转换 高低64 32 16 8 高转低 强转 低转高 自动
package 面向对象.重写.类型转换;
public class Person {
}
package 面向对象.重写.类型转换;
import 面向对象.重写.A;
public class App {
public static void main(String[] args) {
//类型之间的转化:基本类型转换 高低64 32 16 8 高转低 强转 低转高 自动
/* char
↓
Byte→short→int→long---›float→double */
/*
类型之间的转换 父(高) 子(低)
* */
Person s1 = new Student();//自动转
//s1将这个吧对象转换成Student类型 就可以用 Student类型的方法了
((Student)s1).son();
Student s2 = new Student();
Person P1=s2;
((Student)P1).son();//子类转换父类 后丢失父类没有的方法
//低(子)转高(父)时,由于子已经继承了父的所有,所以删去属于自己的后自然而然就可以转化问父类的;而父想要转子,则需要重新开辟只属于子的空间,则需用强制转换
}
}
//---------------------父Person---------------------
package 面向对象.重写.类型转换;
public class Person {
}
//--------------------子Student--------------------
package 面向对象.重写.类型转换;
public class Student extends Person{
public void son(){
System.out.println("son");
}}
//-----------------子Teacher-------------
package 面向对象.重写.类型转换;
public class Teacher extends Person{
}
抽象类
抽象类的所有方法继承了它的子类 都必须实现它的方法 爸爸、爷爷的靠不住~~孙子来顶住
extends 单继承 (接口可以多继承)
特点 不能new 只能靠 子类去实现 (约束)
抽象类里面 可以写普通方法
抽象方法必须在抽象类中
package 面向对象.抽象类;
//abstract抽象类
public abstract class Action {
//约束~有人帮我们约束
public void doSome(){
}
// 抽象方法 只有方法的名字 没有方法的实现
public abstract void doSme();
}
package 面向对象.抽象类;
//抽象类的所有方法继承了它的子类 都必须实现它的方法 爸爸、爷爷的靠不住~~孙子来顶住
//extends 单继承 (接口可以多继承)
public class A extends Action{
@Override
public void doSme() {
}
// 特点 不能new 只能靠 子类去实现 约束
// 抽象类里面 可以写普通方法
// 抽象方法必须在抽象类中
// 抽象的抽象 约束
}
接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法专业的约束!约束和实现分离:面向接口编程
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能….”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
**接口的本质是契约,**就像我们人间的法律一样。制定好后大家都遵守。
声明类的关键字是class,声明接口的关键字是interface
1.约束
2,定义一些方法 让不同的人实现
3.类 接口中的所有定义都是抽象的 public abstract
4.常量 //常量~public static final
5,接口不能被实例化 .接口没有构造方法
6.interface可以实现多个接口
7.必须重写接口的方法
package 面向对象.接口;
public interface UserService {
//常量~public static final
int AGE=99;
//接口中的所有定义都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
//---------------
package 面向对象.接口;
public interface TimeService {
void timar();
}
//-------------------
package 面向对象.接口;
//类实现接口 implements
//实现了接口的类 就需要重写接口的方法
//多继承 利用接口 实现多少继承
public class UserserviceImpl implements UserService,TimeService{
@Override
public void timar() {
}
//快捷键 Ctrl+i
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
}
内部类
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
1.成员内部类
⒉静态内部类
3.局部内部类
4.匿名内部类
匿名类
package 面向对象.内部类;
public class 匿名类 {
public static void main(String[] args) {
new s().id();
// ad ad = new ad()
new ad(){
@Override
public void diao() {
}
};
}
}
class s{
public void id(){
System.out.println("1");
}
}
interface ad{
public void diao();
}
局部内部类
package 面向对象.内部类;
public class 局部内部类 {
public void id(){
// 局部内部类
class in{}
}
}
package 面向对象.内部类;
public class 成员内部类 {
private int id;
private void id1() {}
public void ouy() {
System.out.println("这是外部类方法");}
class inner {
public void in() {
System.out.println("这是内部类方法");}
// 获得外部类id私有属性和方法
public void getid(){
id=10;
System.out.println(id);}}
public static class inner1 {
public void in1() {
System.out.println("这是静态内部类方法");
/*静态只能访问静态,静态是在类加载时候初始化的,实例访问不到*/}}
}//一个java类中只能有一个public class 但是有n个calls
class a{}
abstract
java的基本数据类型和引用数据类型的区别
基本类型变量存放的是变量值
引用数据类型的变更了存放的是变量的引用(地址)