面向对象(oop)
1.初识面向对象
面向过程思想
具体的 步骤清晰,第一步做什么,第二步做什么
面向对象编程本质就是:以类的方式组织代码,以对象的形式组织(封装)数据
从认识角度考虑是先有对象后有类,是具体的事物。类,是抽象的,是对对象的抽象。
从代码的角度看考虑是先有类后有对象。
2.方法的回顾和加深
public static void main(String[] args) {
// 实例化 这个类new
//非静态方法 ↓ 1.
Student student = new Student();
student.say();
// 2. ↓
new Student().say();
//静态方法直接调用 ↓ static
//Student.say();
}
public void say(){
// say方法
}
}
3.对象的创建分析
类是一种抽象的数据类型,它是对某一种事物整体描述/定义,但是并不能代表某一个具体的事务
例如抽象的概念:动物,植物等
对象是抽象概念的具体实例
创建于初始化对象
使用new关键字创建对象
一个项目应该只存在一个main方法
一个类里面 只有属性和方法
构造器
package com.oop.Demo2;
public class Person {
public String name;
public int age;
//构造器 Alt+(fn)insert
public Person() {
}
//有参构造: 一旦有参构造 想用new对象的话 必须显式定义出来无参构造
public Person(String name) {
this.name = name;
}
//实例化初始值
//1.使用new关键字,本质是在调用构造器
//2.用来初始化值
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
//测试类
/** public class Application {
public static void main(String[] args) {
//实例化了一个对象
Person person = new Person("awdaw",13);
System.out.println(person.name);
System.out.println(person.age);
}
}
* 构造器:
* 1.必须和类名相同
* 2.没有返回值
* 作用:
* 1. new 本质在调用构造方法
* 2. 初始化对象的值
* 注意点:
* 1.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
* this.XXX 代表这个类的
*/
定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
创建对象与内存分析
小结类与对象
1.类与方法
类是一个模板 抽象的,对象是一个具体的实例
2.方法
定义,调用
3.对象的引用
引用类型:基本类型(8种)
对象是通过引用来操作的,从 栈 → 堆
4.属性:字段Field 成员变量
默认初始化:
数:0 0.0
char: u0000
boolean: false
其他引用: 都为null
修饰符 属性类型 属性名 = 属性值
5.对象的创建与使用
必须使用new关键字创造对象,构造器 Person names = new Person( );
对象的属性 names . name
对象的方法 names . say( )
6.类 ( 一个类中 只有属性和方法)
静态的属性 就是属性
动态的方法 方法
4.重点:面向对象的三大特性(封装,继承,多态)
封装(属性私有 get,set)
追求“高内聚,低耦合”
高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉,
低耦合:仅暴露少量的方法给外部使用,
属性私有,get/set
数据的隐藏 通常,应禁止直接访问一个对象数据的实际表示,而应通过操作接口来访问,成为信息隐藏
package com.oop.Demo03;
//类 private私有
public class Student {
//属性私有
private String name;//名字
private int age; //年龄
private char sex; //性别
//因为私有 所以要提供一些可以操作这些属性的方法
// 提供一个public的get、set方法
//get 获取这个数据
public String getName(){
return name;
}
//set 给这个数据设置值
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
// set内可以判断安全性
public void setAge(int age) {
if (age > 120 || age < 0) {
this.age = 3;
} else {
this.age = age;
}
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
测试类
package com.oop;
import com.oop.Demo03.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("wawa");
System.out.println(s1.getName());
s1.setAge(666);//不合法
System.out.println(s1.getAge());
}
/**封装的意义
* 1.提高程序的安全,保护数据
* 2.隐藏代码的实现细节
* 3.统一接口 get set
* 4.提高了系统的可维护性
*/
}
继承
继承的本质是对某一批类的抽象
extends 的意思是“扩展”,子类是父类的扩展。
子类继承了父类,就会拥有父类的全部方法。
//Student子类 继承 Person父类
public class Student extends Person{
}
四个优先级
//public
//protected(受保护的)
//default(默认的)
//private(私有) 用get /set方法操作
继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖,组合,聚合。
继承关系的链各类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用关键子extends来表示
子类和父类之间具有“is ”的关系。
java中类只有单继承,没有多继承
object类
java中所有的类 都默认直接或间接继承object ctrl+h可以查看继承关系
super
方法也是和属性一样的调用
但是权限私有的 private 父类的方法 子类通过super不能调用
super 注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中!
3.super和this不能同时出现调用构造方法。同时则报错
4.定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造。
对比 this
代表的对象不同
this:本省调用者这个对象
super:代表父类对象的应用
前提
this:没有继承也可以使用
super:只能在继承条件才能使用
构造方法
this():本类的构造
super():父类的构造!
方法重写 Override
重写 只和非静态方法有关
测试类
public class Application {
public static void main(String[] args) {
//静态方法和非静态方法区别很大!!
// 静态方法 加了static 方法的调用只和左边定义的数据类型有关
// 重写 只和非静态方法有关
A a = new A();
a.text();
//父类的B引用指向了子类A
B b = new A(); //子类重写了父类
b.text();
}
}
子类A
public class A extends B{
父类B
//重写 只有方法
public class B {
public void text(){
System.out.println("B输出");
}
}
非静态才能重写:需要有继承关系,子类重写父类的方法!
1.方法名必须相同
2.参数列表必须相同,否则就变成方法重载了
3.修饰符: 范围可以扩大 public 》 protected》Default》private
4.抛出异常: 范围可以被缩小 但不能扩大ClassnotFoundException <--Exception(大)
重写:子类方法必须和父类必须一致, 方法体不同
为什么需要重写???
-
父类的功能,子类不一定需要,或者不一定满足!
-
Alt +Insert override
多态
package com.oop.Demo06;
public class Person {
public void run(){
System.out.println("DD666");
}
}
/*
多态注意
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系 类型转换异常! ClassCastException
3.存在条件: 继承关系,方法需要重写,
两个类都有,父类引用指向子类对象!执行子类
个别方法不能被重写
1. static 方法,属于类,不属于实例
2. final 常量 定值
3. private方法: 私有
*/
子类
public class Student extends Person{
测试类
package com.oop;
import com.oop.Demo06.Person;
import com.oop.Demo06.Student;
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();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
((Student)s2).eat();
s1.run();
s2.run();//子类重写了父类的方法,由此执行子类
}
}
多态注意
1.多态是方法的多态,属性没有多态
2.父类和子类,有联系 类型转换异常! ClassCastException
3.存在条件: 继承关系,方法需要重写,
两个类都有,父类引用指向子类对象!执行子类
个别方法不能被重写
1. static 方法,属于类,不属于实例
2. final 常量 定值
3. private方法: 私有
同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
多态存在的条件
有继承关系
父类引用指向子类对象
注意 多态是方法的多态,属性名没有多态性
instanceof 判断一个对象是什么类型
System.out.println(X instanceof Y);//判断能不能编译
X与Y存在有关系就可以
public class Application {
public static void main(String[] args) {
//类型转换之间 父 子
Student student = new Student();
// 高 转 低 可以任意转换无影响 ↓
Person student1 = new Student();
//想让student1这个对象person类 执行 Student类的方法以及独有的run方法
//低转高 就要强制转换
Student student11 = (Student) student1;
//强制转换利用student11对象就可以使用Student
student11.run();
}
}
student对象类 想使用Student类的方法 ((Student)student) . run()
/*
1.父类的引用指向子类的对象
2.把子类转为父类,向上转型,反之父类转子类向下转型:需要强制转换可能会丢失些方法
3.方便方法调用,减少重复的代码
static关键字详解
static静态方法 可以在类中任意调用也可被非静态方法调用
public class Student {
private static int age;//静态的变量
private double score; //非静态的变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
run();//直接调不行,
//必须 new 对象调用
new Student().run();
static 多线程会用到
public class Person {
{
//代码块(匿名代码快) 2.匿名代码块 可以用来赋一些初始值
}
static{
//静态代码块 且执行一次 1.最先执行 跟类一起加载
}
public Person() {
//构造方法 3.最后执行构造
}
}
package com.oop.Demo08;
//静态导入包
import static java.lang.Math.PI;
import static java.lang.Math.*;
public class Text {
public static void main(String[] args) {
System.out.println(random());
}
//通过final定义的类不能继承了,
}
通过 final 定义的类不能继承了,