Java面向对象编程
java的核心思想就是OOP(Object-Oriented Programming)
1初始面向对象
面向过程–面向对象:线性思维–分类思维
对于描述复杂事物,宏观上使用面向对象思路分析整个系统,微观上使用面向过程思路去处理。
本质:以类的方式组织代码,以对象的组织(封装数据)
抽象:抽离出相似的部分。
特性: 封装:把代码里面的数据封装起来,留一个口
继承:子类继承父类所有特性
多态:同一个事物有多种形态
从认识角度:先有对象–抽象出类;类是对对象的抽象
从代码角度:先有类后有对象;类是对象的模板
2方法回顾和加深
方法的定义
修饰符有:
- public
- private
- default
- protected
修饰符 返回类型 方法名 参数列表 返回值
public String sayHello (参数类型+形式参数名) {
return+返回值 }
//通常都会加static
方法的调用
- 静态方法 加static的就是
- 非静态方法 不加static的
- 值传递
package com.OOP.demo01;
import com.eighteen.method.Demo;
//值传递
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;
import com.eighteen.method.Demo;
//引用传递: 对象 ,本质还是值传递
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 = "纪伟";
}
}
//定义了一个Person类,有一个属性:name
class Person{
String name;
}
3对象的创建分析
类与对象的关系
类是一种抽象的数据类型,它是对某一类事物整体的描述/定义,但是并不能代表某一个具体的事物。
对象是抽象概念的具体实例。
创建对象
构造器!!!
- 类中构造器也称为构造方法,是在进行创建对象的时候必须调用的;构造器具有以下两个特点
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
- 作用
- new,本质在调用构造方法 默认有一个无参的不显示的构造器
- 初始化对象的值
- 注意点
- 一旦定义有参构造之后,就必须显示定义一个无参构造!!!
- 快捷键创建构造器:alt+insert
- this. 是代表当前类的,而后面=的值是传进来的值
Person类
package com.OOP.demo02;
import org.omg.CosNaming.NamingContextExtPackage.StringNameHelper;
public class Person {
//一个类即使什么都不写 也会存在一个方法
//显示的定义构造器
String name;
int age;
//这就是一个构造器
//实例化初始值
//1.使用new关键字,本质是在调用构造器
//无参构造
// public Person(){
// this.name = "qinjiang";
// }
//
// //有参构造
// public Person(String name){
// this.name = name;
// }
//快捷键alt+insert
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Application*测试类
public class Application {
public static void main(String[] args) {
//实例化了一个对象
Person person = new Person("kuangshen", 22);
System.out.println(person.name);
}
4面向对象的三大特性
封装
该漏的漏,该藏的藏;程序设计追求高内聚,低耦合。
代码:属性私有,get/set
封装的作用:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统可维护增加了
学生类:
package com.OOP.demo04;
//学生类 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快速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>110 || age <=0){
System.out.println("年龄不合法");
}else {
this.age = age;
}
}
//学习()
//睡觉()
}
Application类
package com.OOP;
import com.OOP.demo02.Person;
import com.OOP.demo03.Pet;
import com.OOP.demo04.Student;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//实例化对象
Student s1 = new Student();
s1.setName("纪伟");
System.out.println(s1.getName());
s1.setAge(12);
System.out.println(s1.getAge());
}
}
继承
补充:final修饰的类 不可以被继承!!!final之后断子绝孙~
继承的本质是对一批类的抽象,从而对世界更好的建模
extends扩展。子类是父类的扩展。
Java中只有单继承没有多继承。
Ctrl+H :打开继承关系的一个树!
Object类
在Java中所有类都默认直接或间接的继承Object类
**父类:Person类 **
package com.OOP.demo05;
//人的类
public class Person {
public void say(){
System.out.println("说了一句话");
}
//修饰符有:public/private/default/protected这四种
//public 可以在其他类里面调用;
//private 则需要先在当前类里面定义一个方法才能在其他类里面使用
public int money = 10_0000_0000;
private float debat = 11111f;
//使用alt+insert插入下面的get和set方法
//因为是debat是私有修饰符;所以需要使用封装的操作
public float getDebat() {
return debat;
}
public void setDebat(float debat) {
this.debat = debat;
}
}
子类:Student和Teacher类
package com.OOP.demo05;
//学生 is 人
//派生类 子类
//子类继承了父类,就会拥有了父类的全部方法!
public class Student extends Person{
}
测试类:Application类
package com.OOP;
import com.OOP.demo05.Person;
import com.OOP.demo05.Student;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//实例化一个student对象
Student student = new Student();
//虽然student类里面没有say()方法,但是因为其继承Person类,可以直接使用say()
student.say();
// student.setDebat(9999);
/
System.out.println(student.money);
System.out.println(student.getDebat());
}
}
super注意点!!!
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现的子类的方法或者构造方法中
- super和this不能同时调用构造方法
Vs this:
- 代表的对象不同
this:本身调用者这个对象
super:代表父类对象的调用 - 前提
this:没有继承也可以使用
super:只能在继承条件下才可以使用 - 构造方法
this() 本类的构造
super() 父类的构造
父类Person类
package com.OOP.demo05;
import org.omg.CosNaming.NamingContextExtPackage.StringNameHelper;
//人的类
public class Person {
//父类的无参构造器
public Person() {
System.out.println("Person无参执行了");
}
//Person 受保护的属性name
protected String name = "yanjiusheng";
}
}
子类Student类
package com.OOP.demo05;
//学生 is 人
public class Student extends Person{
//隐藏代码;调用了父类的无参构造
//子类的无参构造器
public Student() {
//也可以调用有参构造器,但是必须加参数。
super();//默认隐藏了!调用父类的构造器必须要在子类构造器的第一行
//this()也必须在第一行
System.out.println("Student无参执行了");
}
}
Application测试类
package com.OOP;
import com.OOP.demo05.Person;
import com.OOP.demo05.Student;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//实例化student对象
//只实例化student对象时,默认先走了父类的构造器,然后走了子类的构造器
//可以创造有参构造器!但是前提是必须显示的构造一个无参构造器
Student student = new Student();
}
}
重写重点!!!
重写,需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大;public>protected>default>private
- 抛出的异常:范围可以被缩小,但不能扩大;ClassNotFoundException–>Exception(大)
重写,子类的方法和父类必须一致,方法体不同!
为什么需要重写?
- 父类的功能,子类不一定需要,或者不一定满足!
alt+insert:override
父类B
package com.OOP.demo05;
public class B {
public void test(){
System.out.println("B=>test()");
}
}
子类A
package com.OOP.demo05;
//重写都是方法的重写,和属性无关
public class A extends B{
//Override 重写
@Override//注解:有功能的注释
public void test() {
super.test();
}
}
测试类Application
package com.OOP;
import com.OOP.demo05.A;
import com.OOP.demo05.B;
//一个项目应该只存在一个main方法
public class Application {
public static void main(String[] args) {
//静态的方法和非静态的方法区别很大!
//静态方法 //方法的调用之和左边,定义的数据类型有关
//非静态方法:重写只和非静态方法有关!!!!
A a = new A();
a.test();//静态调用A
// A.test();//静态调用(加static)
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();//B
}
}
多态
动态编译:类型:可扩展性更强
多态注意点!!!
- 多态是方法的多态,属性没有多态
- 父类和子类得是有联系的! 类型转换异常!ClassCastException!
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
- static 方法,属于类,它不属于实例
- final 修饰的,无法重写;它是常量
- private 修饰的方法,也不可以重写。
父类Person类
package com.OOP.demo06;
public class Person {
public void run(){
System.out.println("run");
}
}
子类Student类
package com.OOP.demo06;
public class Student extends Person{
// public void run(){
// System.out.println("son run");
// }
//alt+insert 子类重写父类的run方法
@Override
public void run() {
System.out.println("son run");;
}
public void eat(){
System.out.println("eat");
}
}
测试类Application类
package com.OOP;
import com.OOP.demo06.Person;
import com.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();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
s2.run();//如果子类没有重写,那么就执行父类的;如果子类重写了父类的方法,那么就执行子类!!!
s1.run();//如果子类没有写方法那么就是继承父类;如果子类重写了方法那就是直接调用子类的方法。
// s2.eat();//因为s2的引用类型是Person,Person没有eat()方法
}
}
instanceof
父类Person类;子类Student;子类Teacher类
测试类Application类
package com.OOP;
import com.OOP.demo06.Person;
import com.OOP.demo06.Student;
import com.OOP.demo06.Teacher;
//一个项目应该只存在一个main方法
public class Application {
//静态的方法和非静态的方法区别很大!
public static void main(String[] args) {
//类与类之间的关系列出来就清楚了
//Object -> Person -> Student
//Object -> Person -> Teacher
//Object -> String
Object object = new Student();
// System.out.println(X instanceof Y); //X和Y之间有没有继承关系,看编译能不能通过
//instanceof 判断类型是否像似;前提两个类型得有点联系才行
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(student instanceof String); //编译报错
}
}
类型转换
之前学过基本数据类型转换。
Application类
package com.OOP;
import com.OOP.demo06.Person;
import com.OOP.demo06.Student;
import com.OOP.demo06.Teacher;
//一个项目应该只存在一个main方法
public class Application {
//静态的方法和非静态的方法区别很大!
public static void main(String[] args) {
//类型之间的转化:基本类型转换 高转低
// 父 子
//高 低
Person ob = new Student();
//将ob这个对象转换成Student类型,那么就可以使用Student类型的方法了
// Student student = (Student) ob;
// student.go();//把这两句话写成一句话 就是下面的形式
((Student) ob).go();
Student student1 = new Student();
//把student1转为Person 低 - 转 - 高
//子类转换为父类,也就是低转高,可能会丢失自己本来的一些方法!
student1.go();
Person person = student1;
//person.go();//原来student1还可以调用自己的go方法,而转为Person类型后就不能调用go方法了 这就是丢失
}
}
/*
1. 父类引用指向子类的对象
2. 把子类转换成父类,向上转型,直接转
3. 把父类转换成子类,向下转型,强制转换
4. 方便方法的调用,减少重复的代码!简洁
封装,继承,多态! 抽象类,接口。
*/
Static
package com.OOP.demo07;
//Static :
//静态导入包
import static java.lang.Math.random;
import static java.lang.Math.PI;
public class Student {
//Static 描述方法 就是静态方法;表述属性就是静态变量
private static int age;//静态的变量
private double score;//非静态的变量
//非静态方法
public void run(){
System.out.println("run");
}
//静态方法
public static void go(){
System.out.println("go");
}
public static void main(String[] args) {
Student s1 = new Student();
//通过对象去调用
System.out.println(s1.age);
System.out.println(s1.score);
//通过类去调用
System.out.println(Student.age);
// System.out.println(Student.score);//非静态的变量不能使用类名去访问
//如果是静态的变量,一般都使用类名.变量的方式;Student.age static对于很多类都共享
Student.go();//静态的就可以直接使用;非静态的就不行,需要new一个对象才行
go();//在自己这个类中的也可以直接使用
Student student = new Student();
student.run();
student.go();;
}
}
代码块
package com.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 person = new Person();
System.out.println("===================");
Person person1 = new Person();
}
}
5抽象类和接口
抽象类
就是加上一个abstract修饰;修饰类就是抽象类;修饰方法就是抽象方法。
- 不能new这个抽象类,只能靠子类去实现它;相当于一个约束!
- 抽象类中可以写普通方法~
- 抽象方法必须存在在抽象类中~
抽象的抽象:约束~
package com.OOP.demo08;
//abstract 抽象类 extends:单继承~ (接口可是实现多继承)
public abstract class Action {
//普通的一个非静态方法
public void dosomething1(){
}
//抽象方法,只有方法名字,但是没有方法的实现。它的子类会帮他实现这个方法。
public abstract void dosomething();
}
接口(抽象思想的精髓)
1对比
- 普通类:只有具体的实现
- 抽象类:具体实现方法和规范(抽象的方法)都有;相当于约束
- 接口:只有规范!自己无法写方法!专业的约束;约束和实现分离:面向接口编程~
2作用
- 约束
- 定义一些方法,让不同的人实现~
- 方法都是public abstract
- 常量都是public static final
- 接口不能被实例化~接口中没有构造方法
- 使用implements可以实现多个接口~
- 实现接口必须要实现接口中的方法~
接口!
package com.OOP.demo09;
//抽象的思维!!!java 架构师~写接口~
//定义的关键字 interface ;接口都需要有实现类
public interface UserService {
//接口中的常量,默认都是public static final修饰的
public static final int AGE = 99;
//一般不会再接口中定义常量!!!一般都是在接口定义方法!!!
//接口中的所有定义其实都是抽象的
//接口中默认的方法都是public abstract void... 所以今后接口中不写了!!!
public abstract void run();
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}
实现接口的类!
package com.OOP.demo09;
//抽象类 extends
//类可以实现接口 implements 接口
//实现了接口的类,就必须重写接口中的方法!!!
//可以同时实现两个接口;利用接口实现了多继承!!!
public class UserServiceImpl implements UserService, TimeService{
@Override
public void run() {
}
@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() {
}
}
6内部类及OOP实战
1内部类和外部类
package com.OOP.demo10;
public class Outer {
private int id;
public void out(){
System.out.println("这是外部类的方法~");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法~");
}
//1.内部类可以获得外部类的私有属性!!!
public void getID(){
System.out.println(id);
// out();
}
}
}
测试类Application
package com.OOP;
import com.OOP.demo10.Outer;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类~
Outer.Inner inner = outer.new Inner();
inner.in();
}
}
2一个文件里面多个类
3局部内部类
package com.OOP.demo10;
public class Outer {
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
4没有名字初始化类
package com.OOP.demo10;
public class Test {
public static void main(String[] args) {
//没有名字初始化类;不用将实例保存到变量中~
new Apple().eat();
//没有名字初始化接口~
new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple{//类
public void eat(){
System.out.println("1");
}
}
interface UserService{//接口
void hello();
}
简单小结类与对象
1类与对象
- 类是一个模板:抽象的;
- 对象是一个具体的示例;
2方法
方法的定义和调用
- 定义:public String sayHello (参数类型+形式参数名) {
return+返回值 }
//加static就是静态的,不加就是非静态的 - 调用:静态调用和非静态调用
- 静态调用就是直接 类名.方法
- 非静态调用 需要先实例化类 然后对象.方法
3方法的引用
引用类型:基本类型(8种)
对象是通过引用来操作的:栈–>堆
4属性
字段Field 成员变量
默认 初始化:
数字: 0 0.0
char: u0000
boolean: false
引用: null
修饰符 属性类型 属性名 = 属性值
5对象的创建和使用
- 必须使用new 关键字来创建对象 Person jiwei = new Person(); 构造器
- 对象的属性 jiwei.name
- 对象的方法 jiwei.sleep()
6类
- 静态的属性 属性
- 动态的方法 方法
一个类只能包含这两个东西