抽象
抽象类概述: 不能具体化对象的类,叫做抽象类 例如:动物类--拿不出动物的对象(只能找到子类的对象)
抽象方法概述:在抽象类中,有一些方法,不知道如何实现,这样的方法,叫做抽象方法
例如:动物类中有叫的方法,但不知道如何描述---抽象方法
类抽象作用:自身限制了具体化,只能实例化子类对象---更自然使用多态
抽象方法作用:作为模板使用,意味着子类必须重写该方法
抽象类:主要用在多态中,是前面多态的优化
用法:1.直接赋值多态 2.参数多态 3.返回值多态
抽象类的特点:
1、抽象类不能实例化对象
2、抽象类可以有构造方法
3、抽象类中也可以没有抽象方法(一般不会这么做)
4、抽象类中可以有非抽象的方法
5、抽象方法不能出现在普通类中
6、子类不一定必须要重写抽象类的抽象方法,可以把自身变为抽象类
7.抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类
抽象类的作用:
1、可以被子类继承,提供共性属性和方法
2、可以声明为应用,更自然的使用多态
抽象类直接多态:
abstract class Animal{ //抽象类
public Animal() { //有构造方法 通过默认的super()调的
}
//抽象方法 不能具体实现的方法,但必须要有---模板
public abstract void bark();
public void test() {
}
}
如果抽象类的方法是抽象方法,子类必须要进行处理:
1.把自身变为抽象类
2.子类必须实现抽象类的重写方法
/*abstract*/ class Dog extends Animal{
@Override
public void bark() {
System.out.println("旺财在叫");
}
}
public class Abstract1 {
public static void main(String[] args) {
//Animal animal = new Animal(); //抽象类不能具体化
Animal animal = new Dog(); //直接赋值多态
animal.bark();
}
}
抽象类参数多态:
//案例:老师开着法拉利牌的交通工具上班,自行车,汽车,飞机等都是交通工具
//分析:类:老师,交通工具(父类) 飞机,自行车,汽车(子类) 行为:开, 运行
abstract class Utils{ //抽象类
public abstract void run(); //抽象方法---模板
}
class Bike extends Utils{
@Override
public void run() {
System.out.println("自行车在运行");
}
}
class Car extends Utils{
@Override
public void run() {
System.out.println("汽车在运行");
}
}
class Teacher{
public void start(Utils utils) {//实参传子类对象
utils.run(); //调用子类重写方法
}
}
public class Abstract2 {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.start(new Bike()); //老师开自行车
teacher.start(new Car()); //老师开汽车
}
}
静态
静态(static)可以修饰属性和方法,称为静态属性(类属性)、静态方法(类方法)。
静态成员是全类所有对象共享的成员。
在全类中只有一份,不因创建多个对象而产生多份。
不必创建对象,可以之间通过类名访问。
非静态属性实例化多个对象每个对象都有独立的成员属性
class Girl{
String name;
public void wash() {
System.out.println("女朋友"+name+"在洗衣服");
}
}
public class Static1 {
public static void main(String[] args) {
Girl girl1 = new Girl();
girl1.name = "小丽";
Girl girl2 = new Girl();
girl2.name = "翠花";
girl1.wash(); //小丽
girl2.wash(); //翠花
}
static+属性==静态属性
java五大存储区域:堆、栈、方法区、本地方法区(例如存放c代码)、寄存器区(与cpu有关)
重点分析堆、栈、方法区。
堆:存new对象,成员属性
栈:存局部变量
方法区:存class 资源 ,静态区,常量池(字符串常量)只有一份共享资源。
静态属性实例化多个对象,每个对象共享同一份静态属性
静态属性与成员属性的区别:
1.存储区域不同 静态属性-方法区 成员属性-堆
2.所属资源不同 静态属性属于类 成员属性属于对象
3.优先级问题:静态属性在类加载是就已经加载了,优先于成员属性
4.调用方式不同 静态属性:类名.属性(推荐) 成员属性:对象.属性
class Girl2{
static String name; //静态属性
public void wash() {
System.out.println("女朋友"+name+"在洗衣服");
}
}
public class Static2 {
public static void main(String[] args) {
Girl2 girl1 = new Girl2();
//The static field Girl2.name should be accessed in a static way
Girl2.name = "小丽"; //静态属性推荐使用:类名.属性
Girl2 girl2 = new Girl2();
girl2.name = "翠花";
girl1.wash(); //小丽
girl2.wash(); //翠花
}
}
静态属性应用场景:
/案例: 统计一个类的对象,被创建了多少次
//分析:通过静态属性来统计次数,实例化多个对象应用共享同一个属性,才能统计次数
//应用场景1:处理共享资源
class A{
static int count;
A(){
count++;
}
}
public class StaticAttr1 {
public static void main(String[] args) {
new A();
new A();
new A();
System.out.println("共创建了"+A.count+"次对象");
}
}
//应用场景2:可作为状态值使用(且需要搭配final-最终的)
//案例: 判断男性和女性的状态: 1代表男性 0代表女性
//状态值的好处:可读性更强,可维护性更强
//注意: 往往状态值需要写成: final+static形式--静态常量; 写法:变量全大写,多个单词用_拼接
public class StaticAttr2 {
static final int SEX_MAN = 1; //男性
static final int SEX_WOMAN = 0; //女性
public static void main(String[] args) {
int sex = getResult();
if(sex==SEX_MAN) { //注意:在当前类中使用静态属性,可省略类名
System.out.println("得到结果为男性");
}else if(sex==SEX_WOMAN){
System.out.println("得到结果为女性");
}
//SEX_MAN = 0; //静态常量,值是不能改变的
//SEX_WOMAN = 1;
}
private static int getResult() {
return SEX_MAN;
}
}
静态方法(重点)
静态方法的特点:
1、静态方法允许直接访问静态成员
2、静态方法不能直接访问非静态成员。
3、静态方法中不允许使用this或super关键字
4、静态方法可以继承,不能重写,没有多态
5、静态方法中不能使用成员属性; 在成员方法中可以使用静态属性
class MyArrays{
int a; //在静态方法中,不能使用成员属性
static int b;
public static String toString(int[] b) {
//System.out.println(a); //加载时机问题,在加载静态资源时,还没有对象,所以不知道对象的属性
//静态方法中,拼接字符串,然后返回
String s = "[";
for(int i=0;i<b.length;i++) {
if(i==b.length-1) { //最后一次,无需加“,”
s+=b[i]+"]";
}else {
s+=b[i]+",";
}
}
return s;
}
public void test() {
System.out.println(b); //在成员方法中可以使用静态属性---加载时机问题
}
}
public class StaticMethod {
public static void main(String[] args) {
//前面学过的静态方法调用:
int[] a = {1,3,5};
int[] b = Arrays.copyOf(a, a.length+1);
System.out.println(Arrays.toString(b));
//相比所学的面向对象操作,此处可直接类名调方法,无需实例化对象
System.out.println(MyArrays.toString(b));
}
}
动态代码块与类加载
动态代码块:
执行: 实例化对象时,触发执行
执行地位:成员属性->动态代码块->构造方法
作用: 给属性赋值(不常用)
类加载的过程:
JVM在首次加载类时,通过classpath找到class文件;然后将class文件加载到内存中;
然后可以知道类中的所有信息,包括包名,类名,属性,方法等等信息。
加载时机:创建对象,创建子类对象,访问静态属性,访问静态方法,
主动加载:Class.forName(全限定名)
如何触发加载class:
class A{
String a = "成员属性";
//动态代码块
{
System.out.println(a); //成员属性
System.out.println("动态代码块");
}
A(){
System.out.println("构造方法");
}
static int b = 4; //静态属性
//静态方法
public static void test() {
System.out.println("静态方法");
}
}
class B extends A{
}
public class StaticCode1 {
public static void main(String[] args) throws ClassNotFoundException {
//new A(); //实例化自身对象-加载A.class
//new B(); //实例化子类对象-加载A.class
//System.out.println(A.b); //静态属性加载A.class
//A.test(); //静态方法加载A.class
Class.forName("com.qf.test4.A"); //通过传入全类名,触发加载A.class(反射对象)
}
}
静态代码块:动态代码块前+static
执行地位: 静态属性->静态代码块->静态方法
作用:给静态属性进行初始化及触发其他类的加载;例如数据库驱动的加载
静态代码块与动态代码块测试进行结合后,实例化对象的过程---测试:
class C{
static String s = "静态属性";
static {
System.out.println(s);
System.out.println("静态代码块");
}
public static void show() {
System.out.println("静态方法");
}
}
public class StaticCode2 {
public static void main(String[] args) {
C.show();
}
}
对象的实例化过程:
Super类的实例化过程:
1.静态属性
2.静态代码块
3.成员属性
4.动态代码块
5.构造方法
6.成员属性
7.动态代码块
8.Super构造方法
结论: 静态代码块只加载一次;动态代码块,每new一次对象都执行一次
class Super{
String a = "成员属性";
{
System.out.println(a);
System.out.println("动态代码块");
}
public Super() {
System.out.println("Super构造方法");
}
static String b = "静态属性";
static {
System.out.println(b);
System.out.println("静态代码块");
}
}
public class StaticCode3 {
public static void main(String[] args) {
new Super();
System.out.println("===========");
new Super();
}
}
实例化子类的过程
1.父类的静态属性
* 2.父类的静态代码块
* 3.子类的静态属性
* 4.子类的静态代码块
* 5.父类成员属性
* 6.父类动态代码块
* 7.父类构造方法
* 8.子类成员属性
* 9.子类动态代码块
* 10.子类的构造方法
*
//1.先静态,后动态 2.先父类,后子类
class Son extends Super{
String a = "子类成员属性";
{
System.out.println(a);
System.out.println("子类动态代码块");
}
public Son() {
System.out.println("子类Son构造方法");
}
static String b = "子类静态属性";
static {
System.out.println(b);
System.out.println("子类静态代码块");
}
}
public class StaticCode4 {
public static void main(String[] args) {
new Son();
}
}
final使用
final: 最终的,固定不变的
修饰类:最终类-不能被继承(太监类)
修饰方法:最终方法-该方法不能被重写
修饰变量:变量变为常量
//final修饰的类,不能有子类
/*final*/ class A{
//final修饰方法,不能被重写
public /*final*/ void test() {
System.out.println("A的测试方法");
}
}
class B extends A{
@Override
public void test() {
System.out.println("B的测试方法");
}
}
public class Final1 {
public static void main(String[] args) {
}
}
final静态变量和成员变量
//修饰变量包括: 修饰成员变量,修饰静态变量,修饰局部引用变量,修饰局部基本变量
class MyClass{
//1.final修饰成员变量(不常用)
//赋值方式: 1.直接赋值 2.动态代码块 3.构造方法
final int a;//=3; //The blank final field a may not have been initialized
{
//a = 5;
}
MyClass(){
a = 6;
}
//2.final修饰静态变量
//赋值方式: 1.直接赋值 2.静态代码块
final static int b; //= 11;
static {
b = 12;
}
}
public class Final2 {
public static void main(String[] args) {
}
}
final修饰局部变量
//final修饰局部变量: 包括基本变量和引用变量
class Student{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Final3 {
public static void main(String[] args) {
//1.final修饰基本变量
final int a = 3;
//a = 5; //final修饰的变量,不能修改值
//2.final修饰引用变量; 地址不可变;里面的存的值可变
final int[] b = new int[3];
b[0] = 1;
//b = new int[4]; //地址不可变
final Student st = new Student();
//但是属性是可以变的
st.setName("zsf");
//st = new Student(); //地址不可变
}
}