Java入门学习笔记(六)

面向对象编程(OOP)

面向对象编程的本质:分类的思维方法,首先思考需要哪些分类,最后对分类下的细节进行面向过程的思索。适合处理复杂的问题。以类的形式组织代码,以对象的组织(封装)数据。

IDEA添加out目录
Project structure—>Modules—>Add content root—>项目所在文件夹—>out。

构造器

规则

  • 必须和类的名字相同。
  • 必须没有返回类型,也不能写void。

作用
使用new关键字,本质是在调用构造器。
用来初始化值。

注意点
定义了有参构造,如果想使用无参构造,必须定义无参构造。

封装

“高内聚,低耦合”:累的内部细节自己完成,不允许外部干涉,仅暴露少量方法给外部使用。
属性私有,get/set

  • 提高代码安全性,保护数据
  • 隐藏代码实现细节
  • 提高可维护性
继承

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
java中只有单继承,没有多继承。

继承注意点

  • 子类默认调用父类的无参构造。
  • 父类如果有有参构造,子类可通过调用父类的有参构造继承父类,如有子类需要调用父类的无参构造,父类必须定义无参构造。
  • java中所有类默认继承object类

super注意点

  • super()调用父类的构造方法,必须在构造方法的第一个。即子类构造器的第一句是super();。
  • super必须只能出现在子类的方法或者构造方法中。 super和this不能同时调用构造方法。即不能同时出现在子类构造器中。

VS this
代表的对象不同:
this:对象本身。
super:父类对象的引用。

前提:
this:没有继承也可以使用。
super:只能在继承条件下才能使用。

构造方法:
this():本类的构造。
super():父类的构造。

重写

重写(override)都是方法的重写,和属性无关。
需要有继承关系,子类重写父类的方法!(而不是属性)

  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大但不能缩小,public>protected>default>private
  • 抛出的异常:范围,可以缩小,但不能扩大

重写,子类的方法和父类必须要一致,方法体(即里面的代码)不同。

为什么需要重写:

  • 父类的功能,子类不一定需要,或者不一定满足。

静态方法:方法调用只和对象的类型的有关,例:

//A是B的子类,test()是静态方法
B b = new A();
b.test();

此时调用的是类B内的test()方法。

非静态:此时将方法重写,例:

//A是B的子类,test()是非静态方法
B b = new A();
b.test();

此时父类B中的test()方法已被A类重写。

故方法重写只与非静态方法有关。

多态
  • 多态是方法的多态,属性没有多态
  • 父类和子类有联系,类型转换异常 ClassCastexception

同一方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类型是确定的,但可以指向对象的的引用的类型有很多(父类,有关系的类)

存在条件

  • 有继承关系
  • 子类重写父类方法
  • 父类引用指向子类对象

多态注意事项

不能重写的方法:

  • static 方法,属于类,不属于实例;
  • final 常量;
  • private方法
类型转换

instanceof:判断两个类之间是否存在父子关系

  • 父类引用指向子类的对象。
  • 把子类转换为父类,向上转型,无需强制转换,但会丧失子类特有的方法.
  • 把父类转换为子类,向下转型,强制转换。
  • 方便方法的调用,减少重复的代码
static详解

非静态方法可以访问静态方法;
静态方法只能调用静态方法。
原因是类的加载顺序,静态方法随着main一起加载。

静态变量调用

public class Student {
        private static int age;
        private double score;
  
  public static void main(String[] args) {
            Student s1 = new Student();
            System.out.println(Student.age);//静态变量通常使用这种调用方法
            System.out.println(s1.age);
            System.out.println(s1.score);//必须new之后才能调用
        }

代码块

public class Student {
        private static int age;
        private double score;
    {
        //匿名代码块
        System.out.println("匿名代码块");
    }
    
    static{
            //静态代码块,首先被执行,只执行一次
            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 static java.lang.Math.random;

public class Demo01 {
    public static void main(String[] args) {
        System.out.println(random());
    }
}

此时可以直接调用random方法。

注意:final类不能被继承。

抽象类

abstract 抽象类,只能单继承。(接口可以多继承)

public abstract class Action {
    public abstract void doSomething();
}

抽象方法
约束,有人去实现

  • 只有方法名,没有方法的实现
  • 不能new这个抽象类,只能靠子类去实现它
  • 抽象类中可以写普通的方法
  • 抽象方法必须在抽象类中
  • new抽象类的子类后,该抽象类有构造器。

抽象类存在的意义:提高开发效率。

接口

声明关键字:interface
接口就是规范,定义的是一组规则
接口中的所有定义其实都是抽象的

注意点

  • 约束 定义一些方法,让不同的人去实现
  • 方法的类型都是public abstract
  • 常量的类型都是public static final
  • 接口不能被实例化,接口内没有构造方法
  • implements可以实现多个接口
  • 必须要重写接口中的方法
//userService.java
public interface userService {
    //接口中定义的是常量,public static final
    int AGE=99;
    
    //接口中定义的所有方法都是是抽象的,默认是public abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}
timeService.java
public interface timeService {
    void timer();
}
//userServiceImpl.java
//类可以实现接口 implements 接口名称
//实现接口的类,需要重写接口中的方法
//利用接口实现多继承
public class userServiceImpl implements userService,timeService{
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {
    }
}
N种内部类

成员内部类

public class Outer {
        private int id=10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
        public class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }

            //获取外部类的属性
            public void getID(){
                System.out.println("Id: "+id);
            }
        }
}
//一个java文件中可以有多个class类,但是只能有一个public class
class A{
}
public class test extends Outer{
    public static void main(String[] args) {
        Outer out = new Outer();
        //通过外部类来实例化内部类
        Outer.Inner inner=out.new Inner();
        inner.getID();
    }
}

输出:

Id: 10

静态内部类

public class Outer {
        static private int id=10;
        public void out(){
            System.out.println("这是外部类的方法");
        }
        public static class Inner{
            public void in(){
                System.out.println("这是内部类的方法");
            }

            //此时id会报错,这是由于id不是静态常量,将id前修饰符加上static即可
            public void getID(){
                System.out.println("Id: "+id);
            }
        }
}
public class test extends Outer{
    public static void main(String[] args) {
        Outer out = new Outer();
        //通过外部类来实例化内部类,此时直接将Inner类实例化即可
        Inner inner=new Inner();
        inner.getID();
    }
}

局部内部类

public class Outer {
       publid void method(){
       //局部内部类,不建议这样用
       class A{      
       }
    }
}

匿名内部类

public class test extends Outer{
    public static void main(String[] args) {
        //没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();
        new UserService(){
            @Override
            public void Hello() {
            }
        };
    }
}

class Apple{
    public void eat(){
        System.out.println("eat");
    }
}

interface UserService{
    void Hello();
}
异常机制

error一般是程序无法控制和处理的,jvm一般会选择终止线程;exception通常是可以被处理的,程序尽可能处理这些异常。

异常处理5个关键字

  • try
  • catch
  • finally
  • throw
  • throws

捕获异常

public class test {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        //windows中crtl+alt+t快捷生成try
        //Mac中Command+option+t快捷生成try
        try { //try监控区域
            new test().divide(a, b);
        }catch (Error e){//捕获异常,括号内为想要捕获的异常类型
            System.out.println("Error,b不能为0");
        }
        catch (Exception e){//捕获异常,括号内为想要捕获的异常类型
            System.out.println("Exception,b不能为0");
        }
        catch (Throwable e){//捕获异常,括号内为想要捕获的异常类型
            System.out.println("Throwable,b不能为0");
        } finally{//处理善后工作
            System.out.println("finally");
        }
    }
        public void divide ( int a, int b){
            System.out.println(a / b);
        }
}

输出:

Exception,b不能为0
finally

主动抛出异常

public class test {
    public static void main(String[] args) {
        try {
            new test().divide(1,0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } finally {
            System.out.println("程序异常,b不能为0");
        }
    }
    //假设在这个方法,处理不了这个异常。方法上抛出异常用throws
    public void divide(int a, int b) throws ArithmeticException{
       if (b==0){//方法内抛出异常用throw
           System.out.println("程序异常,divide抛出异常");
           throw new ArithmeticException();//主动抛出异常,一般在方法中使用
       }
    }
}

输出:

程序异常,divide抛出异常
java.lang.ArithmeticException
	at demo.Demo17_oop_exception.Test.divide(Test.java:58)
	at demo.Demo17_oop_exception.Test.main(Test.java:10)
程序异常,b不能为0

自定义异常

//MyException.java
public class MyException extends Exception{
     private int detail;
     public MyException(int a){
         this.detail=a;
     }
     //toString:异常的打印信息
    @Override
    public String toString() {
        return "MyException{" + detail + '}';
    }
}
//test.java
public class test {
    public static void main(String[] args) {
        try {
            test(1);
            test(11);
            test(5);
        } catch (MyException e) {
            System.out.println("MyException==>"+e);
        }
    }
    //可能会存在异常的方法
    static void test(int a) throws MyException{
        System.out.println("传递的参数为: "+a);
        if(a>10){
            throw new MyException(a);//抛出异常
        }
        System.out.println("OK");
    }
}

输出:

传递的参数为: 1
OK
传递的参数为: 11
MyException==>MyException{11}

test(5)未运行,这是由于test(11)抛出异常后,被catch捕获,跳过test(5)。

实际应用中的经验总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗漏的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源

参考博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值