Java基础4(类与对象)

本文详细介绍了面向对象编程的基础概念,包括类、对象、封装、继承、多态等核心概念。通过实例展示了如何使用IDEA进行代码调试,如通过Alt+Enter处理错误,以及如何调用构造器和方法。还探讨了异常处理、内部类和抽象类,并提供了自定义异常的示例。文章强调了封装的重要性,以及如何通过继承和多态提高代码的灵活性和复用性。
摘要由CSDN通过智能技术生成

ctrl+双击:一个类,即打开这个类的源码

IDEA红色波浪线出错-->Alt+Enter-->显示异常

属性(字段)+ 方法 = 类(class)

静态的属性 动态的行为

面向对象(oop):分类的思维模式,而面向过程是线性思维模式,面向对象是适合多人协作的复杂问题。

oop的本质:以类的方式组织代码,以对象的形式封装数据。

抽象:把多个共同点抽取出来形成一个类。(抽 像)

从认识论分析:是具体对象抽象成类;

但从代码运行角度分析:是由类这样一个模板新建了一个对象。

方法: 修饰符 返回值类型 方法名(……){

方法体

return 返回值;}

public String Hello{

return "hello world";}   //return:结束方法,返回一个结果。

静态方法(static)调用:类名.方法名 Student.say();

非静态方法调用:实例化(new)这个类: new Student.say(); 一般写作:

Student student = new Student(); //对象类型 对象名 = 对象值

student.say();

*static方法不能调用非static方法,因为static方法是和类一起加载的,而非静态方法在类实例化(new对象)之后在存在,已经存在的不能调不存在的。*

this:表示当前类。 this.name=name(参数传进来的值);this.age=age;

*一个项目应该只存在一个main方法,其他的public class里面都不要写main。*

Student student = new Student();  (alt+enter,enter)//类的实例化,返回一个自己的对象,student对象就是一个student类的具体实例。可以是Student xiaoming = new Student();也可以是Student xiaohong = new Student(); 即一个类可以产生不同的对象。


构造器

用idea打开.class文件:Project Structure -> Modules -> +Add根目录 -> out文件 -> OK,Apply

一个类即使什么都不写,它也会存在一个方法,即构造器。(.class文件自动生成一个方法)

构造器的2个特点(无参):①必须和类的名字相同。②必须没有返回值类型,也不能写void。

构造器的作用:①使用new关键字,本质是在调用构造器。(一旦定义了有参构造,无参就必须显示定义)  ②用来初始化值(对象的值)

快捷键:alt+insert  -> constuctor -> 自动生成有参/无参构造器代码。

自己总结:构造器的作用其实就是用来初始化值,因为在新建对象后会有一个默认值,而构造器的作用就是重写这个默认值。        有参构造在new person(这个括号里"sss"),无参构造在构造器大括号里this.name="sss";


*String预定义类是不可变的,所以就当变量来处理。*

属性的定义:(修饰符) 属性类型   属性名 =  属性值

对象的创建和使用:1.必须使用new关键字创建对象、构造器  Person xiong = new Person();默认有无参构造器(自动生成的)。     2.对象的属性:xiong.name     3. 对象的方法:xiong.sleep()

接口——方法。两个方法相同,则表示方法名和参数列表都相同。

封装

“高内聚,低耦合” ,针对于属性。高内聚——类的内部数据操作自己完成,不允许外部干涉;低耦合——仅暴露少量的方法给外部使用。

private:(属性)私有。例如:private String name,之后就不可以使用Student s1=new Student();s1.name;调用了。

封装后需要设置get,set方法才可以调用数据:

public void setName(String name){                                              public String getName(){

        this.name=name;}                                                                          return this.name;}

main方法:                                                                                      main方法: 

s1.setName("熊”);                                                                            sout(s1.getName());

                        一般都是先set再get,alt+insert自动生成get,set方法

封装的意义:1.提高程序的安全性,保护数据。

2.隐藏代码的实现细节(set方法可以用if语句判断是否满足条件来做一些安全性的判断)

3.统一接口(get,set)

4.提高系统的可维护性。


继承

extends,扩展。   子类是父类的扩展,子类 extends 父类

继承的都是public的东西,private的东西是无法继承的。

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

注意:Java中类只有单继承,没有多继承,直接继承一个,间接继承多个(父子)。

父类有属性:protected String name = "xiong";

子类有属性和方法:private String name = "dan";

                                public void test(String name){

                                        sout(name);     //表示此方法中的属性

                                        sout(this.name);     //调此类

                                        sout(super.name);}   //调用父类

在应用类里面调用:

import com.oop.student;

public class Application{

        psvm{

                Student student = new Student();

                student.test("熊");

最后输出:

dan

xiong

有关子类父类构造器:

1、子类构造器隐藏代码:调用了父类的无参构造,相当于在构造器里面的第一行默认有一个super();这样new子类时父类的方法也new了。

2、注意调用父类的构造器的话,必须要写在子类构造器的第一行。

3、super();和this();不能同时调用构造方法(都得在第一行,要么调父类的,要么调子类的)。

4、若父类无参构造设置成了有参构造而没有加上无参构造,则子类也无法自动生成无参构造。

/*this();方法:表示本类的构造                                        super():表示父类的构造

this:代表本身调用者这个对象                                        super:代表父类对象的引用

this:没有继承也可以使用                                               super:只能在继承条件下使用*/


方法重写

(子类重写父类的方法):重写都是方法的重写,与属性无关。    非静态方法

快捷键:Alt + insert -> Override Methods

@Override     // 有功能的注解,重写

public class A extends B{

        public void test() {

                super.test(); ---重写自己的---> sout("A=>test()"); 

}}                   // B中输出的是"B=>test()"

重写完以后在有psvm的类中调用:

B b = new A();                 /*  类名 对象名 =new 类名()   后面的类名是实际类型,前面的类名是引用类型,实际类型是确定的,引用类型可以有父/子类型。*/

b.test();                 ------>输出:A=>test()   【若子类父类都是static方法的话输出B=>test()】

原因:静态方法是类的方法,而非静态是对象的方法(static修饰的方法归类所有,叫做类的成员,而不是对象的成员)。有static时,b调用了B类的方法;没有static时,b则调用对象的方法,b是A类new的对象所以调用A的方法。

1、静态方法(public static void test()):方法的调用只和左边(定义的数据类型A/B)有关。

2、非静态方法:只有非静态才能重写(子类重写父类的方法)

3、重写只能都是public,不能有private。

重写注意点:

①必须有继承关系  ②方法名必须相同  ③参数列表必须相同  ④修饰符范围可以扩大但不能缩小:

public>protected>default>private

为什么要重写?

子类不一定需要父类的功能 / 父类的功能不能满足子类的需要


多态

多态与重写联系紧密。

一个对象的实际类型是确定的,但可以指向的引用类型就不确定了(父类的引用指向子类)

Student s1 = new Student();

Person s2 = new Student();        //如果子类重写了父类的方法,那就执行子类。   Person是父类型,可以指向子类,但是不能调用子类独有的方法。

Object  s3 = new Student();

对象能执行哪些方法,主要看对象等式左边的(引用)类型。

s2.eat();        //eat方法在Student里有Person里没有,报红。     -----> 回车:  ((student)s2.eat();  //强制转换成student类型。person转student,高转低。

s2.run();         // 若student子类重写了父类Person里的run(),则执行子类的方法。

多态——同一方法可以根据发送对象的不同(student / person)而采用不同的行为方式,重写了执行Student,没有重写执行Person。

多态存在的条件:①有继承关系 【若没有父子关系则出现类型转换异常:ClassCastException】

②子类重写父类方法

③父类引用子类对象     Father f1 = new Son();

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

2、final常量,通过final修饰的类也不能被继承。   final有最终的意思,不能继续进化了。

3、private方法。


instanceof:判断两个类是否有父子关系(返回true/false)     sout ( X instanceod Y);

【若在object-person-student这个域里,则为true,否则为false,

若判断的两个类型父子关系(比如是姊妹关系),则报错】

类型转换:低(子)->高(父)可以自动转换,但可能会丢失自身的一些方法;

父->子需要强制转换:Person a = new Student();

Student b = (Student) a;   b.go();         ==>简化成:((Student)a).go();

多态的作用:方便方法的调用,减少重复的代码。(子类父类可以调用互相的方法)


静态变量(static)推荐使用类名调用:Student.age而不是s1.age,这样就能知道这是一个静态变量。(静态变量才能通过类名调用,非静态调用只能通过对象s1调用)

同样,非静态方法只能通过new 类名().方法名();来调用;静态方法可以直接 类名().方法名();

非静态方法可以访问静态方法,静态方法不能调用非静态方法。

static还可以用来静态导入包

新建一个对象:1.最先执行静态代码块:static{……},一个类只执行一次

2.执行匿名代码块{……},与对象同时产生,用来赋初值。

3.执行构造方法 public Person(){……}


抽象类/抽象方法:

只有方法名字,没有方法的实现:public abstract class Action{

                                                              public abstract void doSomething();  }

抽象类的所有方法,继承了它的子类都必须要实现它的方法,除非子类也是抽象的(那就子子类去实现)。 

public class A extends Action{

        @Override

        public void doSomething{           }

abstract有一个缺陷就是只能实现单继承,而接口便可以实现多继承了。

单继承也就是一个子类只有一个父类

多继承就是一个子类可以有多个父类

抽象类的作用:可提高开发效率,可以让别人来实现它的方法。(当多个类中出现相同功能,但是功能主体不同,这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。)

抽象类的特点:1、不能new这个抽象类,只能靠子类去实现它。

2、抽象类中可以写普通的方法。

3、抽象方法必须在抽象类中。

【抽象类存在构造器,new子类自动执行父类构造】


接口:

本质是契约,像法律一样,制定好后大家都遵守。

(1)普通类:只有实现。

(2)抽象类:实现+规范(抽象方法)

(3)接口:只有规范(约束)                利用接口实现多继承

class ----> interface

接口中所有的定义都是抽象的:

public interface UserService {
    public abstract void add(String name);//public abstract是默认的,接口中所有定义的方法都是抽象的,可写可不写。
}
public interface TimeService {
    void timer();
}
注意:接口都需要有实现类---->以Impl结尾  :

public class UserServiceImpl implements UserService,TimeService{ //实现了接口的类,就需要重写接口中的方法,不重写就会报错
    @Override
    public void add(String name) {

    }

    @Override
    public void timer() {

    }
}

*在接口里定义的属性默认都是常量(public static final)

接口不能被实例化(new),接口中没有构造方法。*


内部类:

成员内部类:

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);//可以获得外部类私有属性!
        }
    }
}

静态内部类:即在Inner类public加上static,一旦加上static后, System.out.println(id)就会报错,除非把 private int id=10;换成 private static int id=10;(静态方法不能访问非静态属性)

局部内部类:

public class Outer2 {
    public void method(){
        class Inner{
            public void in(){
                System.out.println("局部内部类");
            }
        }
    }
}

匿名内部类:

public class Outer3 {
    public static void main(String[] args) {
        new Apple().eat();//没有名字初始化类,不用将实例保存到变量中,节约内存
        UserService userService=new UserService() {//实现接口的类,没有名字
            @Override
            public void hello() {
            }
        };
    }
}
class Apple{
    public void eat(){
        System.out.println("eat");
    }
}
interface UserService{
    void hello();
}

异常:

Error:致命错误,JVM(Java虚拟机)终止线程。

Exception:可被程序处理。

RuntimeException:运行时异常(除了运行时异常其他的几种异常都是可以避免的)

ArrayIndexOutOfBoundsException:数组下标越界

NullPointerException:空指针异常

ArithmetricException:算术异常

MissingResourceException:丢失资源

ClassNotFoundException:找不到类

捕获异常

public class Test1 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try {//try监控区域
            System.out.println(a / b);
        }catch (Exception e){//catch捕获异常
            System.out.println("出现异常,b不能为0");
        }finally {//finally处理善后工作,有无异常都执行,可省略,但如果有IO流等资源需关闭的情况就不可省。
            System.out.println("finaly");
        }
    }
}

catch(想要捕获的异常类型 变量):类型最高是Throwable

Exception:捕获最大的异常

可以有好几个catch,捕获多个异常,其中Throwable放在最后(按从小到大的顺序依次排序:Error<Exception<Throwable

抛出异常

选中System.out.println(a/b);然后ctrl+Alt+T,自动生成try-catch-finally

public class Test2 {
    public static void main(String[] args) {
        /*int a = 1;
        int b = 0;
        try {
            System.out.println(a / b);
        } catch (Exception e) {
            System.exit(0);//最好选择手动结束
            e.printStackTrace();
        } finally {
        }*/

        try {
            new Test2().test(1, 0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        } finally {
        }
        //总结:throw、throws是运行时抛出异常,try-catch是遇到错误也能运行(让程序继续往下走)
    }
    public void test(int a,int b) throws ArithmeticException{//假设在这方法中,处理不了这个异常,则在方法上抛出异常 throws
        if(b==0){
            throw new ArithmeticException();//主动在方法内抛出是throw
        }
        System.out.println(a/b);
        }

}

自定义异常

//自定义异常
public class MyException extends Exception{
    private int detail;
    public MyException(int a) {//便于抛出MyException(a)
        this.detail = a;
    }

    public MyException() {//显示定义无参构造

    }

    //Alt+insert-->toString方法:异常的打印信息
    @Override
    public String toString() {
        return "MyException{" +
                "detail=" + detail +
                '}';
    }
}

//测试
public class TestMyException {
    //可能会存在异常的方法
    static void test(int b) throws MyException{
        System.out.println("传递的参数为:"+b);
        if(b>10){
            throw new MyException(b);//通过throws抛到外面去try-catch,也可以在方法里try-catch
        }
        System.out.println("Ok");
    }

    public static void main(String[] args) {
        try {//自动捕获
            test(19);//1是测试的数据
        } catch (MyException e) {
            System.out.println("MyException=>"+e);//增加处理异常的代码
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值