面向对象之关键字

@(笔记)[面向对象|MarkDown]

07.10

面向对象之关键字

new

要谈new关键字,就必须先说说构造方法,它们2个就是一对好基友.

构造方法

定义
  • 无参构造方法:
    访问修饰符 类名(){ }
  • 带参构造方法
    访问修饰符 类名(参数列表){ }
说明
  1. 构造方法可以被重载;
  2. 没有返回类型(void也算返回类型,只是没有返回值);
  3. 方法名和类名必须一样;
  4. 如果不写,系统会默认提供一个无参构造方法;
  5. 如果写了,系统就不会提供任何构造方法;
  6. 子类不能继承父类的构造方法;
  7. 接口没有构造方法;
作用

产生对象
new 一个对象的时候构造器所要做的事
1. 创建空间;
2. 划分属性;
3. 初始化值;
4. 执行构造方法内的语句;

实例化一个对象

用new关键字实例化一个对象时,所用做的事:
People p = new People();
1. 加载People,class文件进入内存;
2. 在栈内存为p变量申请一个空间(4个字节);
3. 在堆内存为People对象申请空间(大小为类中所有成员变量的大小);
4. 对类中的成员变量进行默认初始化;
5. (如果有)对类的成员变量进行显示初始化;
6. 有构造代码块,先执行构造代码块中的语句;
7. 执行构造方法中的语句;
8. 把堆内存的引用赋给p变量;


static

(类级别的,与对象无关)
可以修饰属性,方法,代码块和内部类;

static修饰属性(类变量)

  • 那么这个属性就可以用类名.属性名来访问,也就是使这个属性称为本领的类变量,为本类对象所共享;

static修饰方法(静态方法)

  • 会使这个方法称为整个类所公有的方法,可以用类名.方法名访问;
  • static修饰的方法,不能直接访问本类中的非静态成员,但本类的非静态方法可以访问本类的静态方法;
  • 在静态方法中不能出现this关键字;
  • 父类中是静态方法,子类中不能覆盖为非静态方法;
  • 在符合覆盖规则的前提下,在父子类中,父类中的静态方法可以被子类中的静态方法覆盖,但是没有多态;
  • 在使用对象调用静态方法时,其实是在调用编译时类型的静态方法;

static修饰初始化代码块

  • 此时初始化代码块叫做静态初始化代码块,这个代码块只在类加载时被执行一次;
  • 可以用静态初始化代码块初始化一个类;
  • 动态初始化代码块,些在类体的{}中,这个代码块在生成对象时运行;

例子

class StaticTest{
    static int a = 3;
    static int b ;
    static void method(int x){
        System.out.println("x = " + x);
        System.out.println("a = " + a);
        System.out.println("b = " + b);
    }
    static {
        System.out.println("静态初始化代码块");
        b = a * 4;
    }
    public static void main(String[] args){
        method(5);
    }
}

输出结果:
静态初始化代码块
x = 5
a = 3
b = 12

执行顺序
1. 首先加载StaticTest类,在静态区开辟空间,给a赋值为3,b赋值为0;
2. 接着执行静态初始化块,先打印一条语句,然后把a*4的值赋给b;
3. 然后把main()方法调入栈中,main()调用method()方法,把3传给x;
4. 然后打印;

注意:在一个static方法中引用任何实例变量都是非法的.

main()中的static

一般情况下,主方法是静态方法,所以可调用静态方法,主方法为静态方法是因为它是整个软件系统的入口,而进入入口时系统中没有任何对象,只能使用类调用。

说明

在有static定义的类的外面,static方法和变量能独立于任何对象而被使用.
例如想从类的外部调用一个static方法:
className.method();
或者调用一个static属性:
className.属性名;
这就是Jaba如何实现全局功能和全局变量的一个控制版本.
例子

class StaticDemo{
    static int a = 42;
    static int b = 99;
    static void callMe(){
        System.out.println("a = " + a);
    }
}
class StaticByName{
    public static void main(String[] args){
        StaticDemo.callMe();
        System.out.println("b = " + StaticDemo.b);
    }
}

输出结果:
a = 42
b = 99

最后一点:static成员不能被其所在class创建的实例访问的.

简单来说
1. 如果不加static修饰的成员是对象成员,也就是归每个对象所有;
2. 加static修饰的成员是类成员,就是可以由一个对象直接调用,为所有对象公有.

从内存的角度来看static

类加载的过程中,类本身也是保存在文件中的(字节码文件保存着类的信息),
java通过I/O流把类文件读入JVM,这个过程称为类的加载.
JVM会通过类路径(classpath)来找字节码文件.
需要的时候才会进行类的加载,生成对象时是先加载后构造.
类变量,会在加载时自动初始化,初始化规则和实例变量相同.
注意:
类中的实例变量是在创建对象时被初始化的.
static修饰的属性,是在类加载时被创建并进行初始化,
类加载的过程只有一次,也就是类变量只会被创建一次.

静态非静态成员的调用

  • 静态成员能直接调用静态成员;
  • 非静态成员不能调用静态成员,能调用非静态成员;
    原因:
    从内存的角度,static修饰的成员是随着类的加载而创建的,
    如果此时用静态成员调用非静态成员,则会报错,
    因为在内存中还没有这个非静态成员;
    非静态成员只有在实例化对象的时候才在内存中创建,所以非静态成员可以调用静态成员.
    说白了就一句话:

先出生的不能娶还没有出生的;(指腹为婚不在讨论的范围之内)
后出生的长大了可以娶先出生的(现在很流行啊),也可以娶一起出生的;


final

最终的意思,不允许改变;
可以修饰变量,方法和类.

final修饰变量

  • 一旦被final修饰的变量,就会变成常量,不能被重新赋值.
  • 常量可以在初始化的时候直接赋值,也可以在构造方法里赋值,
  • 只能二选一,不能为常量重新赋值;
  • 常量没有默认值;
  • 锁定栈,使栈中的数据不可以改变;
  • 静态常量只能在初始化时直接赋值;
关于引用的问题

问题:使用final修饰的变量,是引用不能变还是引用的对象不能变?

final StringBuffer a = new StringBuffer("finalTest");
a = new StringBuffer("");//报编译器错误

a.append("finalTest");//这样可以

所以被final修饰的变量,是引用变量不能变,引用变量所指向的对象中的内容还是可以改变的.

final修饰方法

被final修饰的方法就不能被子类重写.

final修饰类

  • 被final修饰的类将不能被继承.
  • final类中的方法也都是final的.

注意:
final不能用来修饰构造方法.

public static final int MAX = 100;

常量属性定义为static,节约空间
final:因为用final修饰,所以是个常量
public:因为是常量,所以不能更改,public修饰给别人看也没事
static:共享,这样就不用new出来才能使用;

补充说明:
内部类要访问局部变量时,局部变量必须定义为final.

为什么局部内部类不能访问没有被final修饰的局部变量?

从内存中看,当方法里的局部变量所在方法结束时,该变量即在栈内存中消失;而内部类其实是一个类,只有内存中对它的所有引用都消失后,该内部类才”死亡”,即内部类的生命周期可能比局部变量长。如果局部内部类能访问一般的局部变量,则在多线程中,可能当方法结束后,局部内部类(是线程类时)还在使用局部变量。为了避免方法内的变量脱离方法而存在的现象发生,于是java规定局部内部类不能访问一般的局部变量。但能访问被final修饰的局部变量。因为常量放在堆内存中的数据段的常量池中

finally

是异常处理语句的一个部分,是异常的同意出口,表示总是执行.
就算是没有catch语句同时又抛出异常的情况下,
finally代码块仍然会被执行。
最后要说的是,finally代码块主要用来释放资源,比如:I/O缓冲区,数据库连接

finalize()

是Object类的一个方法,在垃圾收集器执行的时候,
会调用被回收对象的此方法,
可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等.
JVM不保证此方法总被执行.

abstract

  • 抽象类不能实例化对象,但是有构造方法,抽象类中可以包含属性,抽象类中的构造方法是用来初始化成员属性的;
  • 所有抽象对象必须被重写,除非子类也是抽象类;
  • 可以存在没有抽象方法的抽象类;
  • 有抽象方法的类必须定义为抽象类;
  • abstract type name_method();
  • 只能修饰方法和类;
    剩下的详细总结将在面向对象的特征中介绍.

instanceof

A instanceof B
A对象是否是B对象的实例

public boolean equals(Object obj){
    if(obj instanceof Student){
        if(student.name.equals(name))
            return true;
    }
    return false;
}

this

  1. 对当前类的引用;
  2. 每个对象都有一个隐含的this变量,它可以访问类的所有信息;
  3. 构造方法的相互调用,必须放在构造方法内的第一个语句;
    在重载的构造器中,为了重复利用代码
class Gril {
    private int age;
    private String name;
    //构造方法
    public Gril(int age ,String name){
        this(name);
        this.age = age;
        //this.name = name;
    }
    public Gril(String name){
        this.name = name;
    }
    public Gril(){

    }
    //睡觉的方法
    public void sleep(Car car){
        System.out.println("在车上睡觉");
    }
    public void sleep(Bed bed){
        System.out.println("在床上睡觉");
    }
    public void sleep(){
        System.out.println("在野外睡觉");
    }
}

super

this和super详解
1. this
this.–>此时的this代表当前对象,可以操作当前类中的所有属性和方法;也可以操作当前类父类访问修饰符允许的方法和属性

  1. super代表当前对象的父类,只能操作当前类父类中访问修饰符允许的属性和方法;
    • this不能看到的时候,super也看不到,this能看到的,super还是看不到;
    • 只有在发生重写的时候,才用super调用当前对象的父类中同名的方法和属性;
    • this()调用本类的其他构造方法;
    • super()调用当前对象的父类的构造方法;
    • 都只能放在构造方法的第一行;
    • this()没有默认;
    • super()为默认公共无参构造;

关于super更详细的介绍将在面向对象之继承中见到.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值