一、 面向对象高级一
1. static
1.1 static修饰成员变量
静态,可以修饰成员变量、成员方法。成员变量按照有无static修饰,分为两种:
- 类变量::有static修饰,属于类,在计算机里只有一份,会被类的全部对象共享。
- 实例变量(对象的变量)
public class student{
//类变量
static string name;
int age;//无static修饰属于每个对象的
类变量的访问:
- 类名.类变量(推荐)
- 对象.类变量(不推荐):因为使用对象访问,还需要先创建对象访问,而使用类变量访问,只需类加载到方法区中即可访问,不需要new对象去访问。他是属于类的,与类一起加载一次,在内存中只有一份,会被类的所有对象共享。
实例变量的访问:
- 对象.实例变量 每个对象都有一份对应的实例变量
// 目标:掌握有无static修饰成员变量的用法,特点。
//1、类变量的用法。
// 类名.类变量(推荐)
Student.name =“裳华";
// 对象.类变量(不推荐)
Student s1 = new Student();
s1.name =“马冬梅";
1.2 类变量的应用场景
在开发中,如果某个数据只需要一份,且希望能够被共享(访问、修改),则该数据可以定义成类变量来记住。
- 类变量:数据只需要一份,且需要被共享时(访问,修改)
- 实例变量:每个对象都要有一份,数据各不同(如:name、score、age)
- 访问自己类中的类变量,可以省略类名不写,在某个类中访问其他类里的类变量,必须带类名。
1.3 static修饰成员方法
属于类,可以直接用类名访问,也可以用对象访问。
用法与差别与修饰成员变量时一样。
1.4 main方法
- main方法使用static修饰,所以他也是静态方法,即类方法,虚拟机通过main方法所在类名.main方法调用的。
- 执行main方法时,可以接收数据,java HelloWorld 1 2 3即可,或者使用idea设置启动时自动传参数,但是在实际开发中一般用不到。
1.5 类方法的应用场景
类方法最常见的应用场景是做工具类。
- 工具类中的方法都是一些类方法,每个方法都是用来完成一个功能的,工具类是给开发人员共同使用的。
- 提高了代码复用;调用方便;提高了开发效率,程序员只需要使用类名调用相应的函数即可。
工具类中的方法使用类方法的好处
- 实例方法需要创建对象来调用,此时对象只是为了调用方法,对象占内存,这样会浪费内存。
- 类方法,直接用类名调用即可,调用方便,也能节省内存。
- 工具类没有创建对象的需求,所以建议将工具类的构造器进行私有,不让开发者创建不必要的对象,将构造器私有化后即不能创建。
1.6 类方法的使用注意事项
- 类方法中可以直接访问类的成员,不可以直接访问实例成员。因为实例成员属于对象。
- 实例方法中既可以直接访问类成员,也可以直接访问实例成员。
- 实例方法中可以出现this关键字,类方法中不可以出现this关键字的。因为类方法不需要对象即可使用,this此时没有指对象,会报错。
1.7 代码块(用的少,了解下,看源码,会方便)
- 代码块是类的5大成分之一(成员变量、构造器、方法、代码块、内部类)
- 代码块分为两种:
- 静态代码块: 格式:static{}
- 特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也只会执行一次。
- 作用:完成类的初始化,例如**:对类变量的初始化赋值**。当被赋值的值很复杂时,会使用该方法赋值,如socket类源码中。赋值是两个很复杂的对象,将其塞入静态代码块赋值,同时可以使用try catch做异常判断。
- 静态代码块: 格式:static{}
System.out.println(Student.number);
System.out.println(student.number);
System.out.println(Student.number);
实例代码块:
- 格式:{}
- 特点:每次创建对象时,执行实例代码块,并在构造器前执行。
- 作用:和构造器一样,都是用来完成对象的初始化的,例如**:对实例变量进行初始化赋值**。
- 重要用途:记录对象创建日志,构造器比较多减少每个重复代码,所以将日志写在实例代码块中了。
1.8 static的应用知识:单例设计模式
设计模式(Designpattern):解决什么问题,如何编写
- 一个问题通常有n种解法,其中肯定有一种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
- 设计模式有20多种,对应20多种软件开发中会遇到的问题。
单例设计模式:确保一个类只有一个对象。
- 把类的构造器私有。
- 定义一个类变量记住类的一个对象。
- 定义一个类方法,返回对象。
懒汉式单例:拿对象时,才开始创建对象(延迟加载对象)
饿汉式单例:拿对象时,对象早就创建好了,例如下面。急用或单例对象被频繁使用。
A a=A.getA();//此处只需要调用该函数获得对象即可。
public class A {
//2.定义一个类变量记住类的一个对象
private static A a=new A();
//1.必须私有类的构造器
private A() {
}
//3.定义一个类方法返回类的对象
public static A getA(){
return a;
}
}
windows中的任务管理器也是单例模式,一个窗口就是对象。在这些业务场景下,使用单例模式,可以避免浪费内存。
懒汉式单例:拿对象时,才开始创建对象(延迟加载对象),不急用使用对象不频繁的情况。
- 把类的构造器私有。
- 定义一个类变量用于存储对象。
- 提供一个类方法,保证返回的是同一个对象。
package com.oop;
public class B {
private static B b;
//1.必须私有类的构造器
private B() {
}
//3.定义一个类方法返回类的对象
public static B getB() {
if (b == null)
b = new B();
return new b;
}
}
2. 继承
Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。
继承的特点
- 子类能继承父类的非私有成员(成员变量、成员方法)。
继承后对象的创建 - 子类的对象是由子类、父类共同完成的。
B对象可以访问父类的成员,子类对象相当于使用子父类两张设计图共同创建出来的。父子类中对外暴露了什么成员,对象就可以访问什么成员。
2.1 继承的好处、应用场景
- 减少重复代码的编写。把重复代码拆到父类中,将不同类抽象出具有相同特征的基类。再将具体类继承基类。
继承相关的注意事项 - 权限修饰符:public protect(DateFormat) private 缺省(Exception)
- Java是单继承的,Java中的类不支持多继承,但是支持多层继承
- 假设支持多继承,那么AB类中如果拥有同样的方法,但是C继承AB,调用方法,不知道使用谁的方法,故不能多继承。
- Object类
- object类是java所有类的祖宗类。我们写的任何一个类,其实都是object的子类或子孙类,默认继承,不需要明写。例如hashcode、equal和toString方法。
- 即使B类继承A类,那么A类或A的祖父类上最顶层家谱上祖宗也会继承Object类
2.2 方法重写
- 当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
- 注意:重写后,方法的访问,Java会遵循就近原则
方法重写的其它注意事项
- 重写小技巧:使用0verride注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。
- 子类重写父类方法时,访问权限必须大于或者等于父类该方法的权限(public>protected>缺省)。
- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
- 私有方法、静态方法不能被重写,如果重写会报错的。
一般情况:声明不变,重新实现即可,不需关心部分细节。
toString方法默认调用,直接输出对象即调用了,但是默认的toString方法是输出对象的地址,不好用,直接重写满足需求返内容。alt+insert选择toString Idea自己生成重写方法的。
子类中访问其他成员的特点
在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的。先局部变量 再本类变量 找不到去父类找,如果成员冲突或方法重写,使用super访问父类的成员,使用this访问自己的成员。
- 先子类局部范围找。
- 然后子类成员范围找。
- 然后父类成员范围找,如果父类范围还没有找到则报错。
如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法
子类构造器的特点
子类的全部构造器,都会先调用父类的构造器,再执行自己。
每个构造器都默认存在super();就是用来调用父类的无参构造器的。如果父类没有无参构造器,子类的全部构造器都报错了,可以使用super(参数列表),手动调用父亲的有参构造器。
- 默认情况下,子类全部构造器的第一行代码都是 super()(写不写都有),它会调用父类的无参数构造器。
- 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(…),指定去调用父类的有参数构造器。
应用场景:
由于部分变量被拆分到父类中了,然后变量一般被设置为私有的,所以部分变量需要通过父类赋值。
this(…)调用兄弟构造器
细节控:任意类的构造器中,是可以通过this(…)去调用该类的其他构造器的,this和super不能同时出现在构造器中,super和this调用构造器显示写出必须放在第一行,因为要首先调用父类构造器,this的兄弟构造器中也是首先调用父类构造器的。