Java基础整理03

Exercise

Test 03

面向对象


本质:以类的方法组织代码,以对象的组织封装数据

三大特征:封装、继承、多态

类与对象

静态方法:和类一起加载的,一个静态方法只能调用静态的东西

非静态方法:类实例化之后才存在

方法中的实参和形参的类型要一一对应

类名  对象名称 = new  类名();  //类被实例化后才可使用,称为对象
对象名称.属性名       //使用对象访问类中的属性
对象名称.方法名()     //       访问类中的方法   
//首先写一个包含属性和方法的类
public class Student{
    //属性:字段Field(成员变量)
    String name;
    int age;
    //方法
    public void study(){
        System.out.println(this.name+"2001");
    }
}


//main中调用后类被实例化成对象
public class Application{
    public static void main(String[] args){
        Student jc = new Student();  //创建对象
        jc.name = "久诚";
        jc.age = 22;
        System.out.println(jc.name);  //久诚
        System.out.println(jc.age);   //22
    }
}

使用new关键字创建对象时,除了分配内存空间以外,还会给创建好的对象进行默认初始化,以及对类中构造器的调用。

构造方法

构造器即构造方法是在进行创建对象时必须调用的。

​ 特点:1、构造方法没有返回值(不能写void)

​    2、构造方法名称必须和类名相同

​    3、构造方法主要是完成方法对属性的初始化工作

public class Person{
    String name;
    public Preson(){     //无参定义(与下面的有参构造方法互为重载)
    }
    
    public Person(String name){    //有参,一但定义了有参构造,无参就必须显示定义
        this.name = name;    //当使用构造方法赋值时,使用this调用本类的成员属性
    }
}


public class Application{
    public static void main(String[] args){
        Person person = new Person("清清");  //使用new关键字,本质是调用构造器
        System.out.println(person.name);  //清清
    }
}

注:如果不定义构造方法,那么Jvm会自动为该类生成一个无参构造方法

​  如果定义了有参构造方法,Jvm将不再生成无参构造方法

  如果想使用无参构造,显示的定义一个无参构造

创建对象内存分析(了解)

public class Pet{
    public String name;
    public int age;
    
    public void shout(){
        System.out.println)("叫");
    }
}


public class Application{
    public static void main(String[] args){
        Pet dog = new Pet();
        dog.name = "小狗";
        dog.age = 3;
        dog.shout();
        System.out.println(dog.name);
        System.out.println(dog.age);
        Pet cat = new Pet();
    }
}


小结1

数据类型分为基本数据类型和引用数据类型

基本数据类型(8种): 整型:byte(8位1字节)、short(16位2字节)、int(32位4字节)、long(64位8字节)

​      ​ ​    浮点型:float(32位4字节)、double(64位8字节)

​      ​ ​    布尔类型:boolean(8位1字节):true、false

​      ​ ​    字符类型:char(16位2字节)

​     低 ---------------------------------------------------> 高

​      byte、short、char -> int -> long -> float -> double

​     转换顺序: 低容量到高容量是自动转换:byte、short、char 自动转换成 int、long、float、double

​      ​ ​    高容量到低容量是强制转换:

​     运算类型:如果两个操作数中有一个是double类型,那么自动转换成double类型

      ​ ​   如果两个操作数中有一个是float类型,那么自动转换成float类型

      ​ ​   如果两个操作数中有一个是long类型,那么自动转换成long类型

      ​ ​   除此之外,都自动转换成int类型(如果两个short进行运算,也要先转换成int类型)

引用数据类型:类、接口、数组

对象是通过引用来操作的:栈 ----> 堆

封装

private:私有(出了这个类之外不能直接访问到)

如果属性可以封装和不封装时,优先选择封装,如果方法也可选,优先选择不封装。

private 属性类型 属性名称;             //属性封装
private 方法返回值 方法名称(参数){};    //方法封装
public class Student{
    //属性私有
    private String name;
    private int id;
    private char sex;
    
    //提供一些public的get和set方法操作该私有属性
    public String getName(){              //get:获得这个数据
        return this.name;
    }
    public void setName(String name){     //set:给这个数据设置值(set方法里可以写一些安全性判断,校验合不合理)
        this.name = name;
    }
}


public class Application{
    public static void main(String[] args){
        Student s1 = new Student();
        s1.setName("清清");
        System.out.println(s1.getName());   //清清
    }
}

继承(单继承、多实现)

extends:扩展(子类对父类的扩展)

在Java中,所有的类都默认直接或间接继承Object类。

当创建子类对象的时候,首先会创建父类对象(调用父类的构造方法),

      ​ ​    然后才是创建子类对象(调用子类的构造方法)。

class 父类{}                  //定义父类
class 子类 extends 父类{}      //使用extends关键字实现继承
public class Person{
    private int money = 10_0000;    //子类不能继承父类私有的东西,但可以调用父类中的非私有方法来访问私有属性(例如set和get方法)
    public int age = 21;
    public void say(){
        System .out.println("清清");
    }
}

public class Student extends Person{     //子类继承了父类中的全部方法
}


public class Application{
    public static void main(String[] args){
        Student student = new Student();
        student.say();
        System.out.println(student.age);    /*清清
                                              21*/
        //System.out.println(student.money);  //报错,money是父类的私有属性
    }
}

注:子类不能继承父类的构造方法和私有的东西。


super关键字:super调用父类普通方法、 调用父类属性、 调用父类构造方法(必须在构造方法的第一个)

      ​ super必须只能出现在子类的方法或者构造方法中

      ​ super和this不能同时调用构造方法

super和this关键字区别:

 5  前提  没有继承也可以使用  只能在继承条件才可使用

public class Person{
    protected String name = "清清";
    public void print(){
        System.out.println("Person");
    }
}

public class Student extends Person{
    private String name = "花海";
    public void print(){
        System.out.println("Student");
    }
    public void test(String name){
        System.out.println(name);        //传参
        System.out.println(this.name);   //本类
        System.out.println(super.name);  //调用父类属性
    }
        public void tes1(){
        print();
        this.print();
        super.print();   //调用父类普通方法
    }
}


public class Application{
    public static void main(String[] args){
        Student student = new Student();
        student.test("久诚");
        student.test1();
    }
}
public class Person{
    public Person(){
        System.out.println("父类无参");
    }
}

public class Student extends Person{
    public Student(){
        //隐藏代码,调用父类的无参构造方法
        super();  //调用父类的构造器,必须要在子类构造器的第一行
        System.out.println("子类无参");
    }
}


public class Application{
    public static void main(String[] args){
        Student student = new Student();
    }
}



方法的重写:

子类中定义了与父类中重名的方法,称之为方法的重写。

public class B {
    public static void test(){
        System.out.println("B中的test");
    }
}

public class A extends B {
    public static void test(){
        System.out.println("A中的test");
    }
}


public class Application {
    public static void main(String[] args) {
        A a = new A();
        a.test();        //静态绑定:方法的调用只和等号左边定义的数据类型有关
        B b = new B();   //父类的引用指向子类的对象(向上转型)
        b.test();
    }
}

b是A new出来的对象,因此调用了A的方法,因为静态方法是类的方法,而非静态是对象的方法,没有static时,b调用的是对象的方法。

public class B {
    public void test(){
        System.out.println("B中的test");
    }
}

public class A extends B {
    @Override//重写
    public void test(){
        System.out.println("重写B的test");
    }
}


public class Application {
    public static void main(String[] args) {
        A a = new A();
        a.test();
        B b = new B();  //子类重写了父类的方法
        b.test();
    }
}

注:需要有继承关系,子类重写父类的方法时,

  1)方法名、参数列表、返回值类型必须相同,方法体不同。

  2)访问权限不能缩小(public > Protected > Default > private)

  3)父类中的方法不能是私有访问。

  4)抛出异常的范围可以被缩小,但不能扩大。(ClassNotFoundExpection < Expection)

多态

即同一方法可以根据发送对象的不同而采用多种不同的行为方式。

父类 父类对象 = 子类实例;         //向上转型(自动)父类引用指向子类对象
子类 子类对象 = (子类)父类实例;   //向下转型(强制)

instanceof关键字 (类型转换) 引用类型,判断一个对象是什么类型(两个类是否存在父子关系)

对象 instanceof 类;
public class A {
    public void fun1(){
        System.out.println("父类---fun1()");
    }
    public void fun2(){
        System.out.println("父类---fun2()");
    }
}

public class B extends A {
    public void fun1(){  //子类重写父类方法
        System.out.println("子类B--fun1()");
    }
    public void fun3(){
        System.out.println("子类B--fun3()");

    }
}

public class C extends A {
    public void fun1(){
        System.out.println("子类C--fun1()");
    }
    public void fun5(){
        System.out.println("子类C--fun5()");

    }
}


public class Test1 {
    public static void main(String[] args) {
/*        B b = (new B());  //实例化子类对象
          A a = b;   //向上转型
          a.fun1();   //此方法被子类B覆写(多态:表面上看调用的是父类对象,实际运行是子类方法)*/
        fun(new B());  //传递B的实例
        fun(new C());
    }
    public static void fun(A a){    //直接用父类对象接收所有子类里的a.fun1()方法和a.fun2()方法,向上转型只能调用父类和子类都有的方法
        a.fun1();  //子类覆写
        a.fun2();  //子类继承
        if(a instanceof B) {
            B b = (B) a;  //向下转型
            b.fun3();
        }else if(a instanceof C){
            C c = (C) a;
            c.fun5();
        }
    }
}

注:1、多态是方法的多态,属性没有多态。

  2、父类要和子类有联系,否则会发生类型转换异常:ClassCastException

  3、存在条件:继承关系,方法需要重写

      不能重写:1)static方法。属于类,不属于实例

           2)final常量

           3)private私有方法


final关键字:(完结器)

使用final定义类,不能被继承(不能有子类),也就不能被重写。

final声明属性并赋值,不能被修改。

final不能修饰构造方法。


static关键字:

1、static属性

static 属性类型 属性名称;            //全局属性(静态属性、类属性)
static final 常量名 = 值;            //静态常量
static final double PI = 3.14;

2、static方法:静态方法不允许被覆盖,只能重新定义

public static 返回值类型(参数列表){}  //全局方法(静态方法、类方法)

3、代码块

public class Demo01 {
    {     //赋初值
        System.out.println("匿名代码块");
    }
    static {  //只执行一次
        System.out.println("静态代码块");
    }
    public Demo01(){
        System.out.println("构造器");
    }
    public static void main(String[] args) {
        Demo01 d1 = new Demo01();
        System.out.println("----------------------");
        Demo01 d2 = new Demo01();
    }
}



小结2:

访问控制修饰符:

public:类的声明、成员属性、成员方法、不能修饰本地属性

private:不能类的声明、成员属性、成员方法、不能修饰本地属性、继承不到

default:类的声明、成员属性、成员方法

protected:不能类的声明、成员属性、成员方法、继承

只有public和default可以放到class前面

非访问控制修饰符:

static关键字:不能放在类的声明部分、成员属性、成员方法

final关键字:能放在类的声明部分(除抽象类)、成员属性、成员方法、有时可以和static连用

this关键字:表明当前对象(成员属性)、调用本类中其他构造方法

抽象(单继承)(存在约束)

abstract关键字:声明抽象类和抽象方法

abstract class 抽象类名称{
    属性;
    访问权限 返回值类型 方法名称(参数){
        [return 返回值]
    }
    //抽象方法
    访问权限 abstract 返回值类型 方法名称(参数);
    //抽象方法中没有方法体!(抽象类至少包含一个抽象方法,抽象方法只需声明不能实现,所以也不能用static修饰)
}

抽象类不能被实例化,只能通过子类重写去实现抽象方法

抽象方法必须存在于抽象类中,但抽象类里可以有普通方法,可以定义无参构造器

public abstract class A {
    public static final String FLAG = "fmvp";
    private String name = "花海";
    public String getName(){
        return name;
    }
    private void setName(String name){
        this.name = name;
    }
    public abstract void print();  //抽象方法
}

public class B extends A {
    @Override  //方法重写
    public void print() {
        System.out.println("FLAG:" + FLAG);
        System.out.println("姓名:" + getName());
    }
}


public class Test {
    public static void main(String[] args) {
        B b = new B();
        b.print();
    }
}




接口(多继承)(约束和实现分离)

interface关键字:接口的定义

[修饰符] interface 接口名称{
    全局常量;
    抽象方法
}

implements关键字:接口的实现

class 子类 implements 接口A,接口B,...{}  //接口的实现

接口中的所有定义的方法都是抽象的(public abstract),所以接口都需要一个实现类来重写接口中的方法

      定义的属性都是全局静态常量(public static final)(不常用)

public interface A {
    String AUTHOR = "清清";  //全局常量
    void print();
    String getInfo();
}

public interface B {
    void say();
}

public class X implements A, B {
    @Override
    public void say() {
        System.out.println("apple");
    }

    @Override
    public void print() {
        System.out.println("作者:" + AUTHOR);
    }

    public String getInfo() {
        return "aaa";
    }

}


public class Test {
    public static void main(String[] args) {
        X x = new X();
        x.say();
        x.print();
        System.out.println(x.getInfo());
    }
}




N种内部类

在一个类的内部再定义一个类。特点:①编译之后可生成独立的字节码文件:Outer$Inner.class

                 ②内部类可直接访问外部类的私有成员而不破坏封装

                 ③可为外部类提供必要的内部功能组件

成员内部类:内部类能操作外部类的私有属性,成员内部类不能定义静态成员,但可包含静态常量。

public class Outer {
    private int id = 10;
    private String name = "久诚";
    public void out(){
        System.out.println("外部类的方法");
    }
    //成员内部类
    public class Inner{
        private String name = "花海";
        private static final String city = "山东"; //静态常量
        public void in(){
            System.out.println("内部类方法");
            System.out.println(name);              //当内部类、外部类存在重名属性时,优先访问内部类属性
            System.out.println(Outer.this.name);   //打印外部类属性
        }
        public void getID(){                       //获得外部类的私有属性
            System.out.println(id);
        }
    }
}


public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();  //通过外部类实例化内部类
        inner.in();
        inner.getID();
    }
}



静态内部类:不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

public class Outer {
    private int age = 10;
    private String name = "清清";
    public void out(){
        System.out.println("外部类的方法");
    }
    //静态内部类,和外部类级别相同
    static class Inner{
        private String address = "111";
        private static int id = 10;
        public void show(){
            Outer outer = new Outer();    //调用外部类对象属性
            System.out.println(outer.name);
            System.out.println(address);  //调用静态内部类的属性和方法
            System.out.println(Inner.id); //调用静态内部类的静态属性
        }
    }
}


public class Application {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.show();
    }
}

局部内部类:定义在外部类的方法中,作用范围和创建对象范围仅限于当前方法。

      内部类可以访问static,但是static修饰的内部类不能直接访问外部非静态属性。

public class Outer {
    public void method(){
        //局部内部类,不能加任何访问修饰符
        final String name = "花海";  //无法保证变量的生命周期与自身相同,变量必须修饰final(jdk1.8后会自动加final变成常量)
        class Inner{
            private String phone = "111222333";
            public void in(){
                System.out.println(name);  //访问局部变量,变量必须是常量(jdk1.7要求)
                System.out.println(phone);
            }
        }
        Inner inner = new Inner();       //创建局部内部类对象
        inner.in();
    }
}


public class Application {
    public static void main(String[] args) {
        Outer.outer = new Outer();
        inner.in();
    }
}

匿名内部类:没有类名的局部内部类(特征与局部内部类相同),必须继承一个父类或者实现一个接口

      一个java类中可以有多个class类,但只能有一个public class

public class Demo02 {
    public static void main(String[] args) {
        new Apple().eat();  //没有名字初始化类,不用将实例保存到变量中
        Pat pat = new Pat(){
            @Override
            public void hello() {
            }
        };
    }
}
class Apple{
    public void eat(){
        System.out.println("1");
    }
}
interface Pat{
    void hello();
}




异常

异常指程序运行中出现的不期而至的各种状况,如文件找不到、网络连接失败、非法参数等。

异常发生在程序运行期间,它影响了正常的程序执行流程。

public class Demo03 {
    public static void main(String[] args) {
        System.out.println(11/0);
    }
}

Error和Expection

Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。

Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。

Error:

Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。

Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发

生时,JVM一般会选择线程终止。

在虚拟机试图执行应用时,如类定义错误(NoClassDefDoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应

用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。

Expection:

在Exception分支有一个重要的子类RuntimeExpection(运行时异常)

       ArrayIndexOutOfBoundsException(数组下标越界)

       NullPointerException(空指针异常)

       ArithmeticException(算数异常)

       MissingResourceException(丢失资源)

       ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。

这些异常一般是由程序逻辑错误引起的,程序应该尽可能避免这类异常发生。

捕获和抛出异常

关键字:try、catch、finally、throw、throws

捕获异常:

public class Demo03 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try {   //try监控区域
            System.out.println(a/b);
        } catch (Error e) {   //catch(想要捕获的异常类型)捕获异常
            System.out.println("Error");
        } catch (Exception e){
            System.out.println("Exception");
            e.printStackTrace();   //打印错误的栈信息
        } catch (Throwable t){
            System.out.println("Throwable");
        } finally {   //处理善后
            System.out.println("finally");
        }
    }
}

注:假设要捕获多个异常,范围要从小到大,因为他只匹配一次。



抛出异常:

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



自定义异常

public class MyException extends Exception {
    //传递数字>10
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }

    @Override
    public String toString() {        //打印异常信息
        return "MyException{" + detail + '}';
    }
}


public class Test {
    //可能会存在异常的方法
    static void test(int a) throws MyException {
        System.out.println("传递的参数为:"+a);
        if (a > 10){
            throw new MyException(a);  //抛出
        }
        System.out.println("OK");
    }

    public static void main(String[] args) {
        try {
            test(12);
        } catch (MyException e) {
            System.out.println("MyException=>"+e);
        }
    }
}
posted @   旅行的七仔  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示