JAVA面向对象学习笔记(2)

目录

 

1、封装:

2、this:

 

3、static:

4、代码块:

5、继承

6、重写

7、final

8、abstract

9、接口

10、多态

11、内部类

12、包装类

13、可变参数

14、异常

15、finally


1、封装:

用于保护或者防止代码被我们无意中破坏

保护成员属性,不让类以外的程序直接访问和修改 (private,public,getter,setter)

封装原则:

隐藏对象的属性和实现细节,仅公开对外方法,并且控制访问级别

 

2、this:

在Java基础中,this关键字是一个最重要的概念。使用this关键字可以完成以下的操作:

· 调用类中的属性

· 调用类中的方法或构造方法

· 表示当前对象

在一个构造方法A中,调用另一个构造方法B时,必须编写在A的第一行:

Class Person{
    private String name;
    private int age;
    
    Person(){
        调用另一个构造方法时,必须编写在的第一行:
        //设置默认的姓名和年龄
        this.Person("默认姓名",1);
    }
    Person(String name,int age){
        this.name = name;
        this.age = age;
    }
}

 

3、static:

静态成员 在类加载时加载并初始化。

无论一个类存在多少个对象 , 静态的属性, 永远在内存中只有一份( 可以理解为所有对象公用 )

在类中定义一个static变量,无论new多少个类,所有的类都是公用该静态变量

在访问时: 静态不能访问非静态 , 非静态可以访问静态 !

 

4、代码块:

构造方法 与 构造代码块 以及 静态代码块的执行顺序:

静态代码块 --> 构造代码块 --> 构造方法

static{}             {}                       public Person(){}

构造方法可能重载,会有多个,无论执行哪一个构造方法,都会执行构造方法块,所以如果所有的构造方法,都要执行某些命令,就可以写在构造代码块里

类加载参考 https://blog.csdn.net/ns_code/article/details/17881581

 

5、继承

new一个子类前,会先找到该类的父类,先在内存中,把父类创建,才会创建子类

子类构造方法中,调用super构造方法,必须放在子类的第一行

 

6、重写

声明为static和private的方法不能被重写,但是能够被再次声明

重写和重载的区别

 

重写(Overriding)

重载(Overloading)

范围

父子类、接口与实现类

本类

方法名称

一致

一致

参数列表

一定不能修改

必须修改

返回类型

一定不能修改

可以修改

异常

可以减少或删除,但不能扩展

可以修改

 

7、final

final修饰局部变量,如果没有赋默认值,则可以且只能赋值一次

final修饰全局变量,必须在声明是赋值

final修饰类,不能被继承

final修饰方法,不能被子类继承

 

8、abstract

抽象类可以有非抽象的方法

抽象类不能直接new对象,只能new他的非抽象子类

抽象类不能被final声明,因为抽象类必须被继承

抽象类可以有构造函数,而且子类对象实例化的时候的流程与普通类的继承是一样的,都是要先调用父类中的

构造方法(默认是无参的),之后再调用子类自己的构造方法。

new抽象类的子类时,JVM也会创建抽象类到内存中,也会执行构造方法

抽象类必须用public或者protected修饰,不写的话,默认也是public,因为抽象类必须要被继承

子类继承抽象类,必须实现抽象类的抽象方法。如果子类不能实现所有抽象方法,那么子类也必须定义为抽象类

 

9、接口

优点:

1、 降低程序的耦合性

2、 易于程序的扩展

3、 有利于程序的维护

因为接口本身都是由全局常量和抽象方法组成 , 所以接口中的成员定义可以简写:

1、全局常量编写时, 可以省略public static final 关键字,例如:

public static final String INFO = "内容" ;

简写后:

String INFO = "内容" ;

2、抽象方法编写时, 可以省略 public abstract 关键字, 例如:

public abstract void print() ;

简写后:

void print() ;

接口因为都是抽象部分, 不存在具体的实现, 所以允许多继承,例如:

interface C extends A,B{

}

抽象类可以实现接口,但是可以不实现接口中的方法

抽象类和接口的区别

1、抽象类要被子类继承,接口要被类实现。

2、接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。

3、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

4、抽象类使用继承来使用, 无法多继承。 接口使用实现来使用, 可以多实现

5、抽象类中可以包含static方法 ,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明

静态方法)

6、接口不能有构造方法,但是抽象类可以有

 

10、多态

多态:就是对象的多种表现形式

方法的重载 和 重写 也是多态的一种, 不过是方法的多态(相同方法名的多种形态)。

重载: 一个类中方法的多态性体现

重写: 子父类中方法的多态性体现。

类似于基本数据类型的转换:

· 向上转型:将子类实例变为父类实例

|- 格式:父类 父类对象 = 子类实例 ;

· 向下转型:将父类实例变为子类实例

|- 格式:子类 子类对象 = (子类)父类实例 ;

 

11、内部类

成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。

不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默

认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:

外部类.this.成员变量

外部类.this.成员方法

外部使用成员内部类

Outter outter = new Outter();

Outter.Inner inner = outter.new Inner();

匿名内部类的过程中,我们需要注意如下几点:

1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能

继承一个类或者实现一个接口。

2、匿名内部类中是不能定义构造函数的。

3、匿名内部类中不能存在任何的静态成员变量和静态方法。

4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。

5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

6、只能访问final型的局部变量

静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。

静态内部类是不需要依赖于外部类对象的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非

static成员变量或者方法.

 

12、包装类

八种包装类也是分为两种大的类型的:

· Number:Integer、Short、Long、Double、Float、Byte都是Number的子类表示是一个

数字。

· Object:Character、Boolean都是Object的直接子类。

 

13、可变参数

语法:

返回值类型 方法名称(数据类型…参数名称){

//参数在方法内部 , 以数组的形式来接收

}

注意:

可变参数只能出现在参数列表的最后。

 

14、异常

受检异常:没执行的时候,编译器就会提示可能会报错的异常

非受检异常 (RuntimeException的子类):执行程序的时候,才会报的异常

try_catch异常处理流程

1、 一旦产生异常,则系统会自动产生一个异常类的实例化对象。

2、 那么,此时如果异常发生在try语句,则会自动找到匹配的catch语句执行,如果没有在try语句中,则会将异

常抛出.

3、 所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。

 

15、finally

在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生

了异常,最终都要执行此段代码,除非在finally执行之前,包括在执行catch的时候,系统退出了(执行退出命令,程序被关闭,断电,关机等等),这样就不会执行finally中的内容

如果想捕获异常抛出时抛出,又要进行finally

可以这么写。这样就不用写catch,有异常直接抛,并且还能执行finally,

 

try {
    a=123;
}finally {
    //要进行的操作
}

如果在try中return,也会在return前,执行finally。

但是在finally中进行赋值操作,会影响结果

1、引用数据类型:在15行return的时候,会把栈内存中p1的存的值(内存地址0x123)复制一份出来,变成p1_copy=0x123,然后p1_copy准备传给main里的p,这时候执行了p1.age=100的操作,因为p1.age存放在堆内存,就会把堆内存中,0x123中,p1.age的值,改为100。这时候执行p1=p2,只是把复制前的,在栈内存中的p1的指针,改为0x124,但是实际上传回去的,是复制出来的p1_copy的内存,0x123,而在finally中进行的操作,就是对0x123的值进行修改,所以,输出p的时候,age=100

public class Main {


    public static void main(String[] args) {
        Person p = haha();
        System.out.println(p.age);//输出的结果为100
    }
    private static Person haha() {
        Person p1 = new Person();
        Person p2 = new Person();
        try {
            p1.age = 10;
            p2.age = 20;

            return p1;
        } catch (Exception e) {
            return null;
        }finally {
            p1.age = 100;
            p1 = p2;
            p2.age = 300;
        }
    }
}
class Person{
    int age;
}

 

2、非引用数据类型:在执行13行return的时候,会先把栈内存中,a1存的值10。复制一份出来为a1_copy,然后准备把a1_copy=10传回去,准备阶段中,a1=100,a1=a2,都是对复制前的a1进行操作,不影响实际传回去的a1_copy的值。因为对非引用类型进行修改,都是在栈内存中进行修改。所以把a1=100,不会对a1_copy进行操作,所以结果输出的也是10。

public class Main {


    public static void main(String[] args) {
        int a = haha();
        System.out.println(a);
    }
    private static int haha() {
        int a1 = 10;
        int a2 = 200;
        try {

            return a1;
        } catch (Exception e) {
            return 0;
        }finally {
            a1 = 100;
            a1 = a2;

        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值