面向对象
面向过程&面向对象
- 面向过程
- 步骤清晰简单 第一步做什么 第二部做什么
- 适合处理一些较为简单的问题
- 面向对象
- 物以类聚 分类的思维模式 思考问题首先会解决问题需要那些分类 然后对这些分类进行单独思考。最后 才对某个分类下的细节进行面向过程的思索
- 适合处理复杂的问题 需要多人协作的问题
对于描述复杂的对象 未来从宏观上把握 从整体上合理分析 我们需要使用面向对象的思路来分析整个系统 但是具体到微观操作 仍然需要面向过程的思路来处理
面向对象的本质就是 以类的方式组织代码 以对象的组织数据
三大特性:
- 封装
- 继承
- 多态
类方法的调用
类方法有两种形式一种是静态方法(方法声明前加关键字static)另一种是非静态方法
public class Student{
public static void say1(){
System.out.println("我是静态方法");
}
public void say2(){
System.out.println("我是非静态方法");
}
}
/****************************************/
public static void main(String[] args){
//调用对象的静态方法 可以直接使用类来调用
Student.say1();
//调用对象的非静态方法 需要先实例化一个对象 由对象来调用
Student student = new Student();
student.say2();
}
类与对象的关系
类是一种抽象的数据类型 它是对某一类事物整体描述/定义 但是并不代表某一个具体的实物
对象是抽象概念的具体实例 具体的实物
使用new关键字创建对象 除了分配内存空间之外 还会给创建好的对象进行默认的初始化以及对类中结构器的调用
类中的构造器 也称为构造方法 是在进行创建对象的时候必须要调用的 并且有以下两个特点
- 必须和类的名字相同
- 必须没有返回类型 也不能写void
public class Person{
String name;
//使用new关键字 实质上是在调用构造器
//用来初始化值
public Person(){
}
//有参构造
public Person(String name){
this.name = name;
}
//这里有两个构造器 一个有参数一个无参数 类似于方法重载 在new的时候可以根据传递的参数 来选择调用那个构造方法
}
封装
程序设计要追求"高内聚 低耦合" 高内聚就是类的内部数据操作细节自己完成,不允许外部干涩;低耦合 仅暴漏少量的方法给外部使用
/*优点
1. 提高程序的安全性 保护数据
2. 隐藏代码的实现细节
3. 统一接口
4. 增加系统可维护性
*/
public class Student{
private String name;//private表示这是一个私有属性 只能类内部的方法调用
public String sex;//public 这是一个公用的属性 可以直接使用类访问
//只能通过公用的方法访问类的私有属性
public String Getname(){
return this.name;
}
public void Setname(String name){
this.name = name;
}
}
继承
继承的本质是对某一批类的抽象
extends 的意思是扩展 子类是父类的扩展
- 继承是类和类之间的关系 除此之外 类和类之间还有依赖 组合 聚合等
- 继承关系的两个类 一个为子类(派生类) 一个为父类(基类) 子类继承父类 使用关键字extends来表示
public class Father{
private String money = "10个打不溜";
public String Getmoner(){
return this.money;
}
public void Setmoney(String money){
this.money = money;
}
}
//继承父类 只有但继承没有多继承 即一个父亲可以有多个儿子 但一个儿子只能由一个父亲 且私有(private)的东西无法被继承 包括属性和方法
public class Son extends Father{
}
super
super是用来指向继承父类 可以用它来访问父类里面的方法或者属性 且只能出现在子类的方法或者构造方法中 只能在继承的类中才能调用
public class Father{
private String money = "10个打不溜";
public String name;
public String Getmoner(){
return this.money;
}
public void Setmoney(String money){
this.money = money;
}
}
public class Son extends Father{
public String name;
public Son(){
super();//调用父类的构造方法,必须在构造方法的第一个
}
public void Printname(String name){
System.out.println(name);//打印传递来的参数name
System.out.println(this.name);//打印子类的属性name
System.out.println(super.name);//打印父类的属性name
}
}
方法重写
重写都是方法的重写 和属性无关
有继承关系的两类 其中父类的引用可以执行子类
public class B{
public static void test(){
System.out.println("B()");
}
}
public class A extends B{
public static void test(){
System.out.println("A()");
}
}
A a = new A();
a.test();//A()
B b = new A();
b.test();//B()
则变量根据本身的数据类型 调用不同类的静态方法
重写的作用方法是类中的非静态方法 只有在方法声明中没有加关键字static修饰的方法才可以重写
public class B{
public void test(){
System.out.println("B()");
}
}
public class A extends B{
public void test(){
System.out.println("A()");
}
}
A a = new A();
a.test();//A()
B b = new A();
b.test();//A()
重写:需要有继承关系 子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 修饰符范围可以扩大但不能缩小 public>protected>default>private
- 抛出的异常:范围可以被缩小但不能放大
为什么需要重写:
- 父类的功能 子类不一定需要或者满足
多态
即同一种方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的 但可以指向对象的引用的类型有很多
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
public class B{
public void test(){
System.out.println("B(test)");
}
}
public class A extends B{
public void test(){
System.out.println("A(test)");
}
public void test1(){
System.out.println("A(test1)");
}
}
//A 能调用的方法都是自己的或者继承父类的
A a = new A();
a.test();//A()
//B 父类 可以指向子类型执行重写的方法 但不能调用子类特有的方法
B b = new A();
b.test();//A()
b.test1()//报错
instanceof
判断对象和类的关系 如果为直系的则返回True 反之返回False
//Object > B > A A继承B B继承Object
//Object > B > C C继承B B继承Object
//Object > String String继承Object
//首先先看对象的类型 如果和要比较的类有继承关系 则能编译通过
//若能编译通过 则看对象new后面的类 和要比较的类是否有继承关系 有则True反之False
Object object = new A();
System.out.Println(object instanceof A);//True
System.out.Println(object instanceof B);//True
System.out.Println(object instanceof Object);//True
System.out.Println(object instanceof C);//False
System.out.Println(object instanceof String);//False
/*****************************************************/
B b = new A();
System.out.Println(b instanceof A);//True
System.out.Println(b instanceof B);//True
System.out.Println(b instanceof Object);//True
System.out.Println(b instanceof C);//False
System.out.Println(b instanceof String);//编译报错 因为b的类型B和String类没有继承关系
/*****************************************************/
A a = new A();
System.out.Println(a instanceof A);//True
System.out.Println(a instanceof B);//True
System.out.Println(a instanceof Object);//True
System.out.Println(a instanceof C);//编译报错 因为a的类型A和C类没有继承关系
System.out.Println(a instanceof String);//编译报错 因为a的类型A和String类没有继承关系
类型转换
和基础类型转换差不多 其中高的只能往低的转 父类>子类
public class B{
public void test(){
System.out.println("B(test)");
}
}
public class A extends B{
public void test(){
System.out.println("A(test)");
}
public void test1(){
System.out.println("A(test1)");
}
}
B b = new A();
b.test1();//编译报错
((A)b).test1();//需要类型转换
若子类转换为父类 会丢失属于自己的方法(笨蛋行为)
static关键字详解
加入static的方法或者属性 就可以使得非静态的变量和方法变成静态的变量和方法可以直接由类调用 不需要在实例化一个对象
public class Student{
private static int age;//静态变量
private int score;//非静态变量
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.age);
}
}
静态代码块
public class Student{
static{
System.out.println("静态代码块");
}
{
System.out.println("匿名代码块");
}
public Student(){
System.out.println("构造代码块");
}
public static void main(String[] args){
Student s1 = new Student();
System.out.println("==============");
Student s2 = new Student();
}
}
/*
静态代码块
匿名代码块
构造代码块
==============
匿名代码块
构造代码快
*/
可以看到静态执行然后在执行匿名代码块最后执行构造代码块
且静态代码块自从调用只执行一次
静态导入包
import java.lang.Math.random;//编译报错
import static java.lang.Math.random;//没问题
抽象类
abstract 修饰关键字 只声明不定义
public abstract class A{
//只声明了方法的名字 但没有方法的定义
public abstract void test();
}
//作为抽象类的继承子类 必须要重写父类的抽象方法
public class B extends A{
//只声明了方法的名字 但没有方法的定义
public void test(){
...;
}
}
注意事项
- 不能new抽象类 只能靠子类去实现它
- 抽象类中可以有普通的方法
- 抽象方法必须在抽象类中
接口的定义与实现
普通类 只有具体实现
抽象类 具体实现和规范(抽象方法)都有
接口 只有规范 约束和实现分离
interface 关键字来定义接口
implements 关键字来连接接口
public interface User{
int age = 99;//接口中定义的变量都是静态常量
void add(String a);//接口中定义的方法都是抽象方法
}
public interface User1{
void quary();
}
//连接了接口的类 就必须重写接口中的方法
public class A implements User,User1{
public void add(String a){
...;
}
public void quary(){
...;
}
}
作用:
- 约束
- 定义一些方法 多种实现
- 接口不能被实例化 没有构造方法
内部类
内部类就是在一个类的内部在定义一个类 A类中定义一个B类 则B类算A类的内部类
A类就是B类的外部类
- 成员内部类
- 静态内部类
- 匿名内部类
- 局部内部类
成员内部类
public class Out{
private int id;
public void out(){
System.out.println("外部");
}
class IN{
public void in(){
System.out.println("内部");
}
//可以通过内部类访问外部类的私有属性
public void Gerid(){
System.out.println(id);
}
}
}
Out a = new Out();
//通过外部类来实例化内部类
Out.In b = a.new In();
b.in();
静态内部类
public class Out{
private int id;
public void out(){
System.out.println("外部");
}
class static IN{
public void in(){
System.out.println("内部");
}
//由于此时这是静态内部类 所以不能访问外部类的非静态属性
public void Gerid(){
System.out.println(id);//
}
}
}
匿名内部类
public class Out{
public static void main(String[] args){
new A().test();//不用将实例保存在变量中
}
}
//一个java类中可以有多个class 但是只能有一个public class
class A{
public void test(){
System.out.println("A");
}
}
局部内部类
public class Outer{
public void method(){
class Inner{
public void in(){
}
}
}
}