面向对象 OOP
什么是面向对象
- 以类的方式组织代码 以对象的组织(封装)数据
- 对象是具体的事物 ,类是抽象的 是对对象的抽象
方法的回顾和加深
package com.YuZhang.oop;
import java.io.IOException;
//Demo01 类
public class Demo01 {
//main 方法
public static void main(String[] args) {
}
/*
修饰符 返回值类型 方法名(参数){
// 方法体
return 返回值;
}
*/
public String sayHello(){
return "hello,world";
}
public void hello(){
return;
}
public int max(int a,int b){
return a>b ?a:b;//三元运算符
}
//break 跳出switch 结束循环
//return 方法执行结束 返回一个结果
//方法名 驼峰原则 见名知意
//数组下标越界异常:Arrayindexoutofbounds
public void readFile(String file) throws IOException{
}
}
方法的调用
静态方法与非静态方法的区别
package com.YuZhang.oop;
public class Demo02 {
// //静态方法 static
// public static void main(String[] args) {
// // Student.say();
// }
//非静态方法
public static void main(String[] args) {
//实例化这个类 new
//对象类型 对象名 = 对象值
Student student = new Student();
student.say();
}
// public static void a(){
// b();
// }
//
// public static void b(){
//
// }
// public void a(){
// b();
// }
//
// public void b(){
//
// }
//和类一起加载的
public static void a(){
//b();
}
//类实例化之后才存在
public void b(){
}
}
package com.YuZhang.oop;
//学生类
public class Student {
// //静态方法
// public static void say(){
// System.out.println("学生说话了");
// }
//非静态方法
public void say(){
System.out.println("学生说话了");
}
}
package com.YuZhang.oop;
public class Demo03 {
public static void main(String[] args) {
//实际参数和形式参数的类型要对应
new Demo03().add(1,2);
}
public static int add(int a ,int b){
return a+b;
}
}
package com.YuZhang.oop;
//值传递
public class Demo04 {
public static void main(String[] args) {
int a =1;
System.out.println(a);//1
Demo04.change(a);
System.out.println(a);//1
}
//返回值为空
public static void change(int a){
a = 10;
}
}
package com.YuZhang.oop;
//引用传递:对象 本质还是值传递
// 对象和内存还没有掌握
public class Demo05 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null
Demo05.change(person);
System.out.println(person.name);
}
public static void change(Person person){
//person是一个对象:指向的------>Person person = new Person();这是一个具体的人 可以改变属性
person.name = "yuzhang";
}
}
//定义了一个person类,有一个属性:name
class Person{
String name;//默认值null
}
对象的创建分析
- 对象是具体的事物 ,类是抽象的 是对对象的抽象
- 使用new关键字创建对象
package com.YuZhang.oop.demo02;
//学生类
public class Student {
//属性: 字段
String name;//默认值 null
int age;//默认值 0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//person---> 身高 体重 国家 国籍
package com.YuZhang.oop.demo02;
//规范一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//类是抽象的 需要实例化
//类实例化后会返回一个自己的对象
//student对象就是一个Student类的具体实现
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
xiaohong.name = "小红";
xiaohong.age = 3;
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
}
构造器详解 构造方法(必须掌握)
package com.YuZhang.oop.demo02;//java------> classpublic class Person { //一个类即使什么都不写 也会存在一个构造方法 // 显式定义构造器 String name; //实例化初始值 //1.使用new关键字必须要有构造器, 本质是在调用构造器 //2.构造器一般用来初始化值// public Person(){// this.name = "yuzhang";// } //定义有参后 让无参的构造方法体空掉就行 public Person(){ } //有参构造:一旦定义了有参构造,无参定义就必须显示定义 public Person(String name){ this.name = name;//对象本身的name = 传参的name } //快捷键 alt+insert 生成构造器 }/*构造器: 1、和类名相同 2、没有返回值作用 1、new 本质是调用构造器 2、初始化对象的值注意点: 1、定义有参构造之后,如果使用无参构造,显示的定义一个无参构造 alt + insertthis. */
package com.YuZhang.oop.demo02;//规范一个项目应该只存在一个main方法public class Application { public static void main(String[] args) { //使用new关键词实例化了一个对象 Person person = new Person("yuzhang"); System.out.println(person.name);//null }}
创建对象内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DXM0wEGt-1619828274811)(C:\Users\86177\AppData\Roaming\Typora\typora-user-images\image-20210426202419038.png)]
package com.YuZhang.oop.demo03;import com.YuZhang.oop.demo02.Person;public class Application { public static void main(String[] args) { Pet dog = new Pet(); dog.name = "旺财"; dog.age = 3; dog.shout(); System.out.println(dog.name); System.out.println(dog.age); } Pet cat = new Pet(); }
package com.YuZhang.oop.demo03;public class Pet { String name; int age; //无参构造 public void shout(){ System.out.println("叫了一声"); }}
简单小结类与对象
-
类与对象
- 类是一个模板 抽象
- 对象是一个具体的实例
-
方法
- 定义
- 调用
-
对象的引用
- 引用类型: 除基本类型外(8种)
- 对象是通过引用来操作的:栈------>堆
-
属性:字段Field 成员变量
- 默认初始化:
- 数字:0 0.0
- char :u0000
- boolean: false
- 引用类型:NULL
- 修饰符 属性类型 属性名 = 属性值;
-
对象的创建和使用
-必须使用new 关键字创建对象,构造器 Person yuzhang = new Person();
-对象的属性 yuzhang.name
-对象的方法 yuzhang.sleep()
-
类:
- 静态的属性 属性
- 动态的行为 方法
面向对象三大特征(核心)
封装
- 该露的露 该藏的藏
- 高内聚,低耦合:类的内部数据操作细节自己完成,不允许外部干涉,仅暴漏少量的方法给外部使用
- 属性私有 get/set
package com.YuZhang.oop;import com.YuZhang.oop.demo04.Student;public class Application { public static void main(String[] args) { Student s1 = new Student(); s1.setName("yuzhang"); System.out.println(s1.getName()); s1.setAge(999);//不合法的 System.out.println(s1.getAge()); s1.setAge(-1);//不合法的 System.out.println(s1.getAge()); }}
package com.YuZhang.oop.demo04;public class Student { /* 1.提高程序的安全性,保护数据 2.隐藏代码的实现细节 3.统一接口 形成规范 4.增加了系统的可维护性 */ //属性私有 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 自动生成get set 方法 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 > 120 || age < 0) {//不合法 this.age = 3; } else { this.age = age; } }}
继承
package com.YuZhang.oop.demo05;public class Application { public static void main(String[] args) {// Student student = new Student();// student.say();// System.out.println(student.money); Person person = new Person(); }}
package com.YuZhang.oop.demo05;//在java中 所有的类都直接或者间接继承object//person 人:父类public class Person {//extends object //public //protected //default 不写就是默认的 //private 无法继承 //按优先级排序的// private int money = 10_0000_0000; public int getMoney() {// return money;// } public void setMoney(int money) {// this.money = money;// } public void say(){// System.out.println("说了一句话");// }}
package com.YuZhang.oop.demo05;//学生 is 人:子类//子类继承了父类,就会拥有父类的全部方法public class Student extends Person { Person person;}
package com.YuZhang.oop.demo05;//老师 is 人:子类public class Teacher extends Person {}
super
package com.YuZhang.oop.demo05;public class Application { public static void main(String[] args) {// Student student = new Student();// student.say();// System.out.println(student.money); Student student = new Student(); // student.test("与张"); //student.test1(); }}
package com.YuZhang.oop.demo05;//在java中 所有的类都直接或者间接继承object//person 人:父类public class Person {//extends object //public //protected //default 不写就是默认的 //private 无法继承 //按优先级排序的// private int money = 10_0000_0000; public int getMoney() {// return money;// } public void setMoney(int money) {// this.money = money;// } public void say(){// System.out.println("说了一句话");// } public Person() { System.out.println("Person无参执行了"); } protected String name = "xiaozhang"; public void print(){ System.out.println("Person"); } //私有的东西无法被继承// private void print(){// System.out.println("Person");// }}
package com.YuZhang.oop.demo05;//学生 is 人:子类//子类继承了父类,就会拥有父类的全部方法public class Student extends Person { public Student() { //隐藏代码:调用了父类的无参构造 //super(); //super是隐藏的方法 调用父类的构造器 必须要在子类构造器的第一行 System.out.println("Student无参执行了"); } private String name = "yuzhang"; public void print() { System.out.println("Person"); } public void test1() { print();//Student this.print();//Student super.print();//Person } public void test(String name) { System.out.println(name);//test的参数 System.out.println(this.name);//Student的属性 System.out.println(super.name);//调用父类的属性 }}
-
super注意点: 1.super调用父类的构造方法,必须在构造方法的第一个 2.super必须只能出现在子类的方法或者构造方法中 3.super和this不能同时调用构造方法Vs this: 代表的对象不同: this:本身调用者这个对象 super:代表父类对象的引用 前提 this:没有继承的情况下也可以使用 super:只有在继承的条件下才可以使用 构造方法 this(): 本类的构造 super():父类的构造
方法重写
package com.YuZhang.oop;import com.YuZhang.oop.demo05.A;import com.YuZhang.oop.demo05.B;public class Application { //静态方法和非静态方法的区别很大 //静态方法的调用之和左边定义的数据类型有关 和右边new 的无关 //非静态方法:重写 //重写的方法只能是公有不能是私有 public static void main(String[] args) { //方法的调用之和左边定义的数据类型有关 和右边new 的无关 A a = new A(); a.test();//A //父类的引用指向了子类 B b = new A();//子类重写了父类方法 只与非静态方法有关 b.test();//B }}
package com.YuZhang.oop.demo05;//重写都是方法的重写,和属性无关public class B { public void test(){ System.out.println("B=>test()"); }}
package com.YuZhang.oop.demo05;//继承public class A extends B{// public void test(){// System.out.println("A=>test()"); //alt+insert @Override//重写 public void test() { System.out.println("A=>test()"); }}
重写:前提是需要有继承关系,子类重写父类的方法 1.方法名必须相同 2.参数列表必须相同 3.修饰符:范围可以扩大但不能缩小: Public>Protected>Default>Private 4.抛出的异常:范围可以被缩小但不能被放大ClassNotFoundException----->Exception(大)重写:子类的方法和父类必须要一致;方法体不同为什么需要重写: 1.父类的功能子类不一定需要,或不一定满足 Alt+Insert;override
多态
- 可以实现动态编译
- 可以令可扩展性变强
- 定义:同一种方法根据发送对象的不同而采用多种不同的行为方式
package com.YuZhang.oop.demo06;public class Application { public static void main(String[] args) { //一个对象的实际类型是确定的 //new Student(); //new Person(); //可以指向的引用类型就不确定了:父类的引用指向子类 Student s1 = new Student();//子类指向的引用 能调用的方法都是自己的或者继承父类的 Person s2 = new Student();//父类指向的引用 可以指向子类,但不能调用子类独有的方法 Object s3 = new Student(); s2.run();//子类重写了父类的方法 执行子类的方法 s1.run(); //对象能执行哪些方法 主要看对象左边的类型 和右边关系不大 //s2.eat();//父类指向的引用 可以指向子类,但不能调用子类独有的方法 ((Student)s2).eat();//强制转换 高转低 s1.eat(); }}
package com.YuZhang.oop.demo06;public class Person { public void run(){ System.out.println("run"); }}
package com.YuZhang.oop.demo06;public class Student extends Person{ @Override public void run() { System.out.println("son"); } public void eat(){ System.out.println("ear"); }}/*多态的注意事项 1.多态是方法的多态 2.父类和子类,有联系 无联系的类会产生类型转换异常ClassCastException 3.存的条件: 继承关系 方法需要重写 父类的引用指向子类对象 Father f1 = 呢哇Son(); 不能重写的方法: 1.static方法 属于类 不属于实例 2.final 常量 3.private 私有 */
instanceof 关键字
/*
//Object>String
//Object>Person>Student
// Object>Person>Teacher
Object object = new Student();
//System.out.println(x instanceof y);//能不能编译通过看的是x与y是否存在父子关系 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);//false 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);//编译报错 //System.out.println(person instanceof String);//编译报错}*/
类型转化
package com.YuZhang.oop.demo06;public class Application { public static void main(String[] args) { //类型之间的转化: 父 子 //高 低 Person obj = new Student(); //obj.go();//报错 //student将这个对象转换为Student类型 我们就可以使用Student类型的方法了 Student obj1 = (Student) obj; ((Student) obj).go(); //子类转化为父类可能会丢失自己本来的一些方法 Student student = new Student(); student.go(); Person person = student; //person.go();//报错 }}/*1.父类的引用指向子类的对象2.把子类转换为父类:向上转型 不用强制转换3.把父类转换为子类:向下转型 需要强制转换4.方便方法的调用,减少重复的代码抽象:封装、继承、多态 */
package com.YuZhang.oop.demo06;public class Person { public void run(){ System.out.println("run"); }}
package com.YuZhang.oop.demo06;public class Teacher extends Person{}
package com.YuZhang.oop.demo06;public class Student extends Person { public void go(){ System.out.println("go"); }}
static关键字详解
package com.YuZhang.oop.demo07;//静态导入包import static java.lang.Math.random;import static java.lang.Math.PI;public class Test { public static void main(String[] args) { System.out.println(random()); System.out.println(PI); } //final 修饰的变量不能被继承}
package com.YuZhang.oop.demo07;public class Person { //2 赋初值 { //匿名代码块 System.out.println("匿名代码块"); } //1 只执行一次 static { //静态代码块 永久只执行一次 System.out.println("静态代码块"); } //3 public Person() { System.out.println("构造方法"); } public static void main(String[] args) { Person person1 = new Person(); System.out.println("==========================="); Person person2 = new Person(); }}
package com.YuZhang.oop.demo07;//staticpublic class Student { private static int age;//静态的变量 多线程 private double score;//非静态的变量 public void run(){ go(); } public static void go(){ //run();//报错 } public static void main(String[] args) {// Student s1 = new Student(); System.out.println(Student.age);// //System.out.println(Student.score);//报错// System.out.println(s1.age);// System.out.println(s1.score); new Student().run(); Student.go(); go(); }}
抽象类和接口
抽象类
- abstract修饰符
package com.YuZhang.oop.demo08;public class Application { public static void main(String[] args) { //Action action = new Action();//报错 }}
package com.YuZhang.oop.demo08;//abstract 抽象类:类 extends:单继承~ (接口可以多继承) 插座~public abstract class Action { //约束~有人帮我们实现 //abstract,抽象方法,只有方法名字,没有方法的实现 public abstract void doSomething(); //1.不能new这个抽象类,只能靠子类去实现他:约束 //2.抽象类里可以写普通方法 //3.抽象方法必须在抽象类中 //抽象的抽象:约束 public void hello(){ //可以有方法体 } //思考题? 抽象类不能new对象 但是存在构造器吗? 存在 //抽象类存在的意义 提高开发效率}
package com.YuZhang.oop.demo08;//抽象类的所有方法,继承了它的子类,都必须要实现他的方法~除非子类也是抽象类public class A extends Action{ @Override public void doSomething(){ }}
接口
- 只有规范!自己无法写方法~专业约束!约束和实现分离:面向接口编程
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有
package com.YuZhang.oop.demo09;//interface 定义的关键字,接口都需要有实现类public interface UserService { //属性都默认public abstract final(常量) int AGE =99; //接口中的所有定义的方法都是抽象的 public // public abstract void run();//可直接向下面一样定义 默认public abstract void run(String name); void add(String name); void delete(String name); void update(String name);//改 void query(String name);//查}
package com.YuZhang.oop.demo09;public interface TimeService { void timer();}
package com.YuZhang.oop.demo09;//类可以实现接口 implements 接口//实现了接口的类,就需要重写接口中的方法//多继承~利用接口实现多继承public class UserServiceImp1 implements UserService,TimeService{ @Override public void run(String name) { } @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 timer() { }}
作用:
1.约束
2.定义一些方法,让不同的人实现~ 10 ----->
3.方法都是 public abstract
4.属性都是 public abstract final
5.接口不能被实例化~,接口中没有构造方法~
6.implements可以实现多个接口
7.实现接口必须要重写里面的方法
内部类及OOP(奇葩代码)
- 在一个类中再定义一个类
package com.YuZhang.oop.demo10;
public class Application {
public static void main(String[] args) {
//new
Outer outer = new Outer();
//通过外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
}
}
package com.YuZhang.oop.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);
}
}
//public static class Inner{}//静态内部类
//一个java类中可以有多个class类,但是只有一个public class类
class A{}
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
package com.YuZhang.oop.demo10;
public class Test {
public static void main(String[] args) {
//Apple apple = new Apple();
//没有名字初始化类,不用将实例保存到变量中
new Apple().eat();
UserService userService = new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple {
public void eat() {
System.out.println("1");
}
}
interface UserService{
void hello();
}