面向对象
什么是面向对象
面向对象编程(OOP)
面向对象变成的本质就是:以类的方式组织代码,以对象的组织(封装数据)。
回顾方法及加深
方法的定义
修饰符
返回类型
break:跳出switch,结束循环和return区别
方法名:注意规范就ok 见名知意
参数列表:(参数类型,参数名) ...
异常抛出
方法的调用:递归
静态方法
非静态方法
形参和实参
值传递和引用传递
this关键字
创建和初始化对象
构造器详解
特点:
1.必须和类的名字相同
2.必须没有返回类型,也不能写void
作用:
1.new本质在调用构造方法
2.初始化对象的值
注意点:
1.定义有参构造之后,如果想使用无参构造,现实的定义一个无参的构造
面向对象创建分析
面向对象内存分析图
![](https://i-blog.csdnimg.cn/blog_migrate/35a90d8d9faa76c541838a2ef97affe4.png)
总结:
1、类与对象
类是一个模板:抽象,对象是一个具体的实例
2、方法
定义和调用!
3、对应的引用
引用类型 基本类型(8)
对象是通过引用来操作的:栈---->堆
4、属性:字段field 成员变量
默认初始化:
数字:0 0.0
char:u0000
boolean:false
引用:null
格式: 修饰符 属性类型 属性名 = 属性值
5、对象的创建和使用
--必须使用new 关键字创造对象,构造器 Person rsc = new Person();
--对象的属性 rsc.name
--对象的方法 rsc.sleep()
6、类:
静态的属性 属性
动态的行为 方法
面向对象三大特性
面向对象三大特性分为继承、封装、多态。
封装(数据的隐藏)
>封装指的是属性私有化,根据需要提供setter和getter方法来访问属性。即隐藏具体属性和实现细节,仅对外开放接口,控制程序中属性的访问级别。
>封装目的:增强安全性和简化编程,使用者不必在意具体实现细节,而只是通过外部接口即可访问类的成员。
我们的程序设计要追求"高内聚,低耦合"。
记:属性私有,get/set
修饰符型关键字
public修饰符:任何类都可以访问protected修饰符:类及其子类或同一个包下的类可 以访问
default(默认不写):类及当前包下可以访问
private修饰符:访问权限仅限于类内部
![](https://i-blog.csdnimg.cn/blog_migrate/8e1bda1c869b39eddca2ce0adc05b224.png)
继承
定义:继承是指将多个相同的属性和方法提取出来,新建一个父类。Java中一个类只能继承一个父类,且只能继承访问权限非private的属性和方法。子类可以重写父类中的方法,命名与父类中同名的属性。
特点:**Java中只有单继承,没有多继承!***
继承目的:代码复用。
Super和this区别
super注意点:
1.super调用父类的构造方法,必须在你构造方法的第一个!
2.super必须只能出现在子类的方法或者构造方法中!
3.super和this不能同时调用构造方法!
Vs this:
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提:
this:没有继承也可以使用
super:只能在继承中使用
构造方法:
this():本类的构造
super():父类的构造!
重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同
3.修饰符:范围可以扩大但不能缩小: public>Protected>Default>private
4.抛出的异常:可以被缩小但不能扩大; ClassNotFoundException-->Exception(大)
重写,子类的方法和父类必须要一致:方法体不同!
为什么需要重写:
1.父类的功能,子类不一定需要或者不一定满足!
当一个子类继承一个父类时,它同时继承了父类的属性和方法。子类可以直接使用父类的属性和方法,如果父类的方法不能满足子类的需求,则可以在子类中对父类的方法进行重写(或覆盖)。
在方法重写时,如果子类需要引用父类中原有的方法,可以使用super关键字。当子类重写父类方法后,在子类对象使用该方法时,会执行子类中重写的方法。
在子类重写父类方法时,需要遵守以下几个重写规则。
□重写方法名、参数和返回类型必须与父类方法定义一致。
□重写方法的修饰符不能比父类方法严格。例如父类方法时用public修饰,那么重写方法不能使用protected或private等修饰。
□重写方法如果有throws定义,那么重写方法throws的异常类型可以是父类方法throws的异常类型及其子类类型。
方法在重写时有很多细节需要注意,否则即使定义了方法,也可能不属于重写,不具有方法重写之后的特征。
重写Alt+Insert :Override;
静态方法和非静态方法的区别很大!
静态方法:方法的调用只和左边定义的数据类型有关。
非静态方法:重写,执行子类重写父类的方法!
多态
定义:多态可以分为两种:设计时多态和运行时多态。
设计时多态:即重载,是指Java允许方法名相同而参数不同(返回值可以相同也可以不相同)。
运行时多态:即重写,是指Java运行根据调用该方法的类型决定调用哪个方法。
多态目的:增加代码的灵活度。
多态注意事项:
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系 类型转换异常 :ClassCastException!
3.多态存在条件:继承关系,方法需要重写,父类引用指向子类对象 Fatherf1=newSon();
无法被重写的方法:
1.static,方法,属于类,他不属于实例
2.final常量
3.private方法
多态类型转换:
1.父类引用指向子类对象
2.把子类对象转换为父类,向上转型
3.把父类转换为子类,向下转型,,强制转换
4.方便方法调用,减少重复的代码
代码:
// 类型之间的转化 父 子
// 子类转换为父类(低转高)可能会丢失自己的本来的一些方法!
Studentstudent=newStudent();
student.go();
Personperson=student;
Personstudent1=newStudent();
//父类转换为子类(高转低),需要强制转换
((Student)student1).go();
多态练习:
Person类(父类)
package com.kuang.oop.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
Student类(子类)
package com.kuang.oop.demo06;
public class Student extends Person{
@Override
public void run() {
System.out.println("son");
}
public void eat(){
System.out.println("eat");
}
}
Application(测试类)
package com.kuang.oop;
import com.kuang.oop.demo03.Pet;
import com.kuang.oop.demo05.A;
import com.kuang.oop.demo05.B;
import com.kuang.oop.demo06.Person;
import com.kuang.oop.demo06.Student;
//一个项目只存在一个main方法
public class Application {
public static void main(String[] args) {
// 一个对象的实际类型是确定的
// new Student();
// new Person();
// 可以指向的引用类型就不确定了:父类的引用指向子类
// Student能调用的方法都是自己的或者继承父类的!
Student s1 = new Student();
// Person父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
/*
如果使用Person类型的对象调用eat方法,则调用不到,因为Person(父类)中没有定义eat
如果方法中都有子类和父类中都有eat,没有重写时,默认调用父类中的eat方法,子类重写时,则调用子类中重写后的方法
对象能执行那些方法,主要好看对象左边的类型和右边关系不大!
*/
((Student) s2).eat(); //子类重写父类的方法,执行了子类的方法
s1.run();
}
}
instanceof详解:
// Object>String
// Object>Person>Student
// Object>Person>Teacher
// System.out.println(X instanceof Y); 必须具备继承关系才能编译通过!
Object object = new Student();
System.out.println(object instanceof Student); //true
System.out.println(object instanceof Person); //true
System.out.println(object instanceof Object); //true
System.out.println(object instanceof Teacher); //false
System.out.println(object instanceof String); //String
System.out.println("================");
Person person = new Student();
System.out.println(person instanceof Student); //true
System.out.println(person instanceof Person); //true
System.out.println(person instanceof Object); //true
System.out.println(person instanceof Teacher); //false
//System.out.println(person instanceof String); //编译错误
System.out.println("==============================");
Student student = new Student();
System.out.println(student instanceof Student); //true
System.out.println(student instanceof Person); //true
System.out.println(student instanceof Object); //true
//System.out.println(student instanceof Teacher); //false
//System.out.println(person instanceof String); //编译错误
Static详解:
1.使用对象调用变量,无论该变量有无static修饰,我们都可以调用;使用类调用时变量时,此变量必须是static修饰,不然调用不到。
2.静态方法只能调用静态方法,因为静态方法跟类一起加载,加载的时候还没有其他方法!
3.动态方法既可以调用动态方法,也可以调用静态方法。
静态代码块: 【执行顺序】
package com.kuang.oop.demo7;
public class Person {
// 2.赋初始值
{
// 代码块(匿名代码块)
System.out.println("匿名代码块");
}
// 1.static只执行一次
static {
// 静态代码块(匿名代码块)
System.out.println("静态代码块");
}
// 3。第三个执行
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person = new Person();
System.out.println("===================");
Person person1 = new Person();
}
}
静态导入包:
package com.kuang.oop.demo7;
//静态导入包~
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类和接口
抽象类
package com.kuang.oop.demo08;
//abstract 抽象类
public abstract class Action {
// 约束~有人帮我们实现
// abstract抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
// 1.不能new这个抽象类,只能靠子类实现它:约束!
// 2.抽象类中可以写普通的方法~
// 3.抽象方法必须写在抽象类
// 4.子类继承了抽象类,必须要实现抽象类的所有方法,除非子类也变成抽象类 单继承
// 抽象的抽象:约束
//思考题? new ,存在构造器吗 抽象类有构造器
// 为什么要用抽象类
// 现实中有些父类中的方法确实没有必要写,因为各个子类中的这个方法肯定会有不同;而写成抽象类,这样看代码时,就知道这是抽象方法,而知道这个方法是在子类中实现的,所以有提示作用。
}
接口
定义:
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
作用:
1.约束
2.定义一些方法,让不同的人实现~
3.方法默认格式: public abstract
4.属性默认格式: public static final
5.接口不能被实例化,接口中没有构造方法。
6.implements可以实现多个接口
7.必须要重写接口中的方法
实现类
package com.kuang.oop.demo09;
public class UserServiceImpl implements UserService,AdminService{
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void query() {
}
@Override
public void go() {
}
}
接口
package com.kuang.oop.demo09;
public interface UserService {
// 接口中的所有定义都是抽象的
// 方法默认格式:public abstract
// 属性默认都是常量,格式: public static final
int age = 10;
void add();
void delete();
void update();
void query();
}
package com.kuang.oop.demo09;
public interface AdminService {
void go();
}
内部类
内部类1)成员内部类
package com.kuang.oop.demo10;
public class Outer01 {
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);
}
}
}
2)静态内部类
package com.kuang.oop.demo10;
public class Outer01 {
private static int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
// 获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
3)局部内部类
package com.kuang.oop.demo10;
public class Outer02 {
// 局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
4)匿名内部类
package com.kuang.oop.demo10;
public class Outer {
//匿名内部类
public static void main(String[] args) {
new A().eat();
B b = new B(){
@Override
public void run() {
}
};
}
}
//一个java类中可以有多个class类,但只能有一个public class类
class A{
public void eat(){
System.out.println("1");
}
}
interface B{
void run();
}
1、局部内部类说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。1.可以直接访问外部类的所有成员,包含私有的2不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final3.作用域:仅仅在定义它的方法或代码块中。4.局部内部类—访问---->外部类的成员[访问方式:直接访问]5.外部类—访问---->局部内部类的成员访问方式:创建对象,再访问(注意:必须在作用域内)记住:(1)局部内部类定义在方法中/代码块(2)作用域在方法体或者代码块中(3)本质仍然是一个类6.外部其他类—不能访问----->局部内部类(因为局部内部类地位是一个局部变量)7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
外部类在方法中,可以创建 内部类 对象,然后调用方法即可
2、匿名内部类(1)本质是类(2)内部类(3)该类没有名字(4)同时还是一个对象说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名1.匿名内部类的基本语法new类或接口(参数列表){类体};
①匿名内部类的语法比较奇特,请大家注意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,,因此可以调用匿名内部类方法。②.可以直接访问外部类的所有成员,包含私有的③不能添加访问修饰符,因为它的地位就是一个局部变量④作用域:仅仅在定义它的方法或代码块中。⑤匿名内部类—访问---->外部类成员[访问方式:直接访问]⑥外部其他类—不能访问----->匿名内部类(因为匿名内部类地位是一个局部变量)⑦如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
3、成员内部类说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。1.可以直接访问外部类的所有成员,包含私有的2.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。3.作用域和外部类的其他成员一样,为整个类体,在外部类的成员方法中创建成员内部类对象,再调用方法.4.成员内部类—访问---->外部类成员(比如;属性)[访问方式:直接访问]5.外部类—访问------>成员内部类 访问方式:创建对象,再访问6.外部其他类—访问---->成员内部类7.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
4、静态内部类说明:静态内部类是定义在外部类的成员位置,并且有static修饰1.可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员2.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。3.作用域:同其他的成员,为整个类体4.静态内部类—访问---->外部类(比如:静态属性)[访问方式:直接访问所有静态成员]5.外部类—访问------>静态内部类访问方式:创建对象,再访问6.外部其他类—访问----->静态内部类7.如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问