• JavaSE-面向对象


    面向对象

    面向对象编程(Object-Oriented Programming, OOP)

    初识面向对象

    面向对象编程的本质就是:以类的方式组织代码,以对象的形式组织封装数据。

    抽象

    从认识论角度考虑是现有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象

    从代码运行角度考虑是先有类后有对象。类是对象的模版

    三大特性:

    封装

    继承

    多态

    方法回顾和加深

    修饰符

    返回值类型

    可以为八大基本类型和引用类型,也可以为void(无返回值),返回值类型为void时,书写return;

    return 与 break区别:

    break:跳出switch,结束循环

    return:结束方法

    参数列表:参数类型+参数名 以及可变长参数

    抛出异常:

     public void readFile(String file) throws IOException {
            
        }
    

    方法的调用

    主要分为有static修饰和无static修饰

    当有static修饰符修饰的方法,是跟类一起加载的,即使类没有被实例化也可以直接调用。类名.方法名 调用该方法

    当无static修饰符修饰的方法,是类实例话后才加载的,不可以直接调用,需要实例化类后通过类的实例化对象进行调用

    //学生类
    public void say(){
      System.out.println("学生说话了");
    }
    //另一个demo类  
    public static void main(String[] args) {
    
      //对象类型  对象名  = 对象值
      student student = new student();
      student.say();
    
    }
    

    值传递和引用传递

    先来看值传递

    //值传递
    public class Demo04 {
        public static void main(String[] args) {
            int a = 1;
            int b = 2;
    
            System.out.println(a);
            System.out.println(b);
    
            System.out.println("===================change===================");
            Demo04.change1(a);
            System.out.println(a);  //1,因为没有把change方法中的值返回出来,所以并没有发生变化
            b = Demo04.change2(b);
            System.out.println(b);
    
        }
    
        //返回值为空
        public static void change1(int a){
            a = 10;
        }
        public static int change2(int b){
            b = 20;
            return b;
    
        }
    

    引用传递

    //引用传递:一般是传递一个对象,本质还是值传递
    //一个class里只能有一个public class,但可以有多个class
    public class Demo05 {
    
        public static void main(String[] args) {
            Person person = new Person();
            System.out.println(person.name); //null
    
    
            //这里不同于值传递,因为在change方法中传入的是person这个对象,修改的是person这个对象的.name属性,所以成功了,
            Demo05.change(person);
            System.out.println(person.name);
    
        }
    
    
        public static void change(Person person){
            person.name = "Zh1z3ven";
        }
    
    
    }
    
    //定义了一个person类,有一个属性:name
    class Person{
        String name;    //null
    }
    
    

    this关键字

    代表当前这个类或者对象

    对象的创建分析

    使用new关键字创建对象

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

    类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点

    1、必须和类的名字相同

    2、必须没有返回类型,也不能写void

    public class Student {
    
        //属性:字段
        String name;    //创建实例化对象时默认为null
        int age;    //0
    
    
        //方法
        public void study(){
            System.out.println(this.name + "is Learning...");
        }
    
    }
    
    public class Application {
    
        public static void main(String[] args) {
            //类是抽象的,需要实例化
            //类实例化后会返回一个自己的对象
            //stduent就是student类的具体实例
    
            Student xiaoming = new Student();
            Student agou = new Student();
    
            xiaoming.name = "小明";
            xiaoming.age = 18;
    
            System.out.println(xiaoming.name);
            System.out.println(xiaoming.age);
    
    
            agou.name = "阿狗";
            agou.age = 18;
    
            System.out.println(agou.name);
            System.out.println(agou.age);
    
        }
    
    }
    

    构造方法

    1、和类名相同

    2、没有返回值

    3、new的本质是在调用构造方法

    4、初始化对象的值

    5、定义有参构造之后,如果想使用无参构造,需要显示的定义一个无参的构造,不然就只有有参构造方法

    6、alt + insert 快捷键

    public class Person {
    
        //一个类即使什么都写,他也会存在一个构造方法
        //构造方法用来初始化值
        /* 形如":
        public Person(){
        }
         */
        //显示定义构造方法
        String name;
    
        //使用new关键字必须有构造方法,本质是在调用构造方法
        //无参构造方法
        public Person(){
            //可以帮助我们初始化对象的属性值
            this.name = "Zh1z3ven";
        }
    
        //有参数构造:一旦定义了有参构造,无参构造方法必须显示定义
        //this.name代表Person类的属性name
        //后面的name为有参构造方法传递的String name参数
        //alt+insert生成构造方法
        public Person(String name){
            this.name = name;
        }
    
        public static void main(String[] args) {
    
            //new 实例化了一个对象
            Person person = new Person();
    
            System.out.println(person.name);
    
        }
    
    }
    

    创建对象内存分析

    代码:

    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);
    
        }
    }
    

    首先会现在方法区加载Application类(类中包括其main()方法,常量池(存放字符串;但int型数字不算在常量池内)),并在栈中加载main方法

    image-20210611201748506

    main方法在栈的最低下,方法的调用执行都在栈中执行。之后运行到Pet dog = new Pet()时,先会在方法区实例化对象所需的模版,即加载一个Pet类,包括该类的属性、常量池和非静态方法。之后当加载完后 讲赋值语句右边的new Pet()赋值给左边的Pet dog时,在栈中会加载一个dog的变量,dog变量暂时只是一个引用变量,引用在堆中生成的实例化对象,类似于指针,该引用指向该实例化对象在堆中的内存地址。

    image-20210611202829021

    而在实例化对象内的shout()是在引用方法区中Pet类中的shout()方法。之后执行到赋值语句时也就是

    dog.name = "旺财";dog.age = 3;
    

    这时会把Application类中的常量池中的旺财赋值给中的name ,之后3赋值给堆中的age ,同时shout()调用的是Pet类中的shout()方法(因为并没有参数传递,所以是同一个方法)

    image-20210611203240461

    在方法区中的静态方法区内,这里存放的是被static修饰符修饰的方法都会同类同时被加载,所以可以不用通过实例化对象就可以直接调用被static修饰的方法。

    image-20210611203429557

    简单小结类与对象

    类是一个模版,是实例化对象的模版

    对象是一个具体的实例,是一个类的实例化对象

    方法的定义

    修饰符 返回值类型 方法名(参数类型 参数名){
    方法体
    ...
    return 返回值;
    }

    方法的调用

    调用方法:对象名.方法名(实参列表)

    Java支持两种调用方法的方式,根据方法是否有返回值来选择。

    return不仅可以返回值,同样可以结束这个方法。例:return 0;结束当前方法。

    当方法返回一个值的时候,方法调用通常被当作一个值赋值给一个变量。

    int larger = max(30, 40);
    

    当方法返回值为void时,方法调用一定是一条语句

    System.out.println("Hello, Zh1z3ven!");
    

    对象的引用

    引用类型:

    基本类型8个(byte、short、int、long、float、double、boolean、char)

    剩下的都是引用类型,对象也是通过引用来操作的:栈-->堆(地址)

    属性:字段field 成员变量,默认初始化(数字:0,char:u000,boolean:false,引用:null)

    属性的定义:

    修饰符 属性类型 属性名 = 属性值

    对象的创建和使用

    必须使用new关键字创建对象 ,注意构造方法,Person zh1z3ven = new Person()

    对象的属性: zh1z3ven.name

    对象的方法: zh1z3ven.sleep()

    静态的属性:属性

    动态的行为:方法

    面向对象三大特性

    封装

    程序设计追求“高内聚、低耦合”,高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

    属性私有 get/set

    属性私有,即用private修饰属性

    get/set,对外提供get set方法使得外部可通过该方法控制属性值

    同时可在set方法中进行安全设置,提高程序的安全性

    /*1、提高程序的安全性2、隐藏代码的实现细节3、统一接口 get、set形成规范4、提高系统可维护性 */public class Student {    //属性私有,加private关键字去修饰属性    private String name;    private int id;    private char sex;    private int age;    //提供一些可以操作这个属性的方法    //提供public的get或set方法    public String getName(){        return this.name;    }    public void setName(String name){        this.name = name;    }    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public char getSex() {        return sex;    }    public void setSex(char sex) {        this.sex = sex;    }    public int getAge() {        return age;    }    public void setAge(int age) {        if (age > 120 || age < 0){            this.age = 3;        }else {            this.age = age;        }    }}public class Application {    public static void main(String[] args) {        Student s1 = new Student();        s1.setName("Zh1z3ven");        System.out.println(s1.getName());        //并不能通过形似s1.name直接访问操作类的属性,但是可以通过某些可被调用的外部方法去操作这个类的私有属性值        //封装:1、属性私有。2、提供可被外部调用的方法去操作私有属性        //alt+insert 选中getter and setter一键生成 get set方法,        //mac为control+return,选中所需要设置的属性即可直接生成        //或者右键选择generate    }}
    

    继承

    extends

    继承的本质是对某一批类的抽象,从而实现对现实世界的更好的建模

    Java中只有单继承没有多继承

    继承就是扩展的意思,子类是对父类的扩展。

    子类可以继承父类的所有方法

    继承是类和类之间的一种关系,除此之外还有依赖,组合,聚合等

    继承关系的俩个类,一个为子类(派生类)一个为父类(基类)。子类继承父类,使用关键字extends表示

    子类和父类之间,从意义上讲因该具有 is a 的关系

    Ctrl + h 可以看该类的继承关系

    object类

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

    super

    如果父类重写了有参构造,最好也写上无参构造,以便后续子类去继承该父类(不然只能调用父类的有参构造方法,默认是调用无参的构造方法)

    1. super调用父类的构造方法必须在构造方法的第一个
    2. super必须只能出现在子类的方法或构造方法中
    3. super和this不能同时调用构造方法

    this代表本身调用者的这个对象

    super代表父类对象的引用

    super必须存在继承关系才可以使用

    this(); 代表本类的构造方法

    super(); 代表父类的构造方法

    //父类public class Person {    public Person(){        System.out.println("Person无参执行了");    }    public int money = 1000000000;    public void say(){        System.out.println("说了一句话");    }    protected String name = "Zh1z3ven";    public void print(){        System.out.println("Person");    }}
    
    //子类public class Student extends Person {    //默认调用了父类的无参构造,调用父类的构造方法必须在子类构造方法的第一行    public Student(){        super();        //也可以不写        System.out.println("Student无参执行了");    }    private String name = "zh1z3ven";    public void print(){        System.out.println("Student");    }    public void test1(){        print();        this.print();        super.print();    }    public void test(String name){        System.out.println(name);//传递的参数name        System.out.println(this.name);//student的属性name        System.out.println(super.name);//父类的属性name    }}
    
    public class Application {    public static void main(String[] args) {        Student student = new Student();        student.test("zz");        student.test1();    }}
    

    方法重写

    重写都是非静态方法的重写(static方法属于类的方法,不属于实例的方法,重写指的是重写实例的方法)

    final修饰的是常量池中的常量,不能被重写。private方法不能被重写。

    子类重写方法的权限修饰符要大于父类 public>protected>default>private

    方法名必须相同、参数列表必须相同(不然就是重载了)

    抛出异常的范围与权限修饰符的范围一致

    子类的方法与父类的方法必须要一致,但是方法体不同

    为什么需要重写?

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

    1. alt+insert / control + return @override
    @Override  //注解:有功能的注释    public void test() {        super.test();			//默认调用父类的方法,也可以自己重写    }
    

    当重写一个非静态父类方法时,在子类中contorl + return即可生成一个重写方法

    静态方法是属于类的方法,当下面test()方法为static修饰的静态方法时,那么会各自调用自己类中的test()方法。因为此时调用的是类中的静态方法;而当没有static修饰时,这时调用的都是A类中的test()方法,因为这时调用的是A的实例化对象加载的test()方法(只有static修饰的方法才会和类一起在方法区中同时加载)

    可以简单理解为一旦子类重写了父类的方法,就执行子类的方法

    class A extends BA a = new A();a.test();//父类引用指向子类B b = new A();b.test()A类中test()实现:System.out.println("A=>test()");B类中test()实现:System.out.println("B=>test()");
    

    多态

    class Student extends PersonStudent s1 = new Student();Person s2 = new Student();Object s3 = new Student();
    

    一个对象的实际类型是确定的(new Student();),但是可以指向的引用类型就不确定了(Student s1/Person s2/Object s3

    多态注意事项:

    • 多态是方法的多态,属性没有多态
    • 父类和子类有联系. ClassCastException类型转换异常
    • 多态存在的条件:继承关系、方法需要重写、父类的引用指向子类对象 Father f1 = new son();

    Instanceof

    判断一个对象是什么类型,可以判断两个类之间是否存在继承关系

        					//Object > String        //Object > Person > Student        //Object > Person > Teacher        Object object = new Student();     //Object类型        System.out.println(object instanceof Student);  //true        System.out.println(object instanceof Person);   //true        System.out.println(object instanceof Object);   //true        System.out.println(object instanceof Teacher);  //false        System.out.println(object instanceof String);   //false        System.out.println("===================================");        Person person = new Student();        System.out.println(person instanceof Object);    //true        System.out.println(person instanceof Person);    //true        System.out.println(person instanceof Student);    //true        System.out.println(person instanceof Teacher);      //false        //System.out.println(person instanceof String);    //编译报错    }
    

    类型转换

    public static void main(String[] args) {        //类型之间的转化:  父      子        //低 --> 高 可以自动转换                //高 --> 低 需要强制转换          Person obj = new Student();                //student将这个对象转换为Student类型,就可以使用Studen类型的方法        Student student = (Student) obj;	//强制转换        student.go();                ((Student) obj).go();							//强制转换        Person person = student;        //自动转化    }    
    

    static关键字

    static : 修饰成员变量或者方法,修饰为静态变量或者静态方法

    被static修饰的属于类,非static的属于对象

    静态变量属于类的变量,存储在方法区的静态方法区内,是一块固定的内存,随着类的加载同时加载,当直接使用类去调用一个变量说明此变量就是静态变量

    非静态方法也可以直接调用静态方法

    静态方法可以直接调用,无需实例化对象

    //static : 修饰成员变量或者方法,修饰为静态变量或者静态方法//被static修饰的属于类,非static的属于对象public class Student {    //静态变量属于类的变量,存储在方法区的静态方法区内,是一块固定的内存,随着类的加载同时加载,当直接使用类去调用一个变量说明此变量就是静态变量    private static int age;     //静态变量    private double score;       //非静态变量    public void run(){        go();                   //非静态方法也可以直接调用静态方法    }    public static void go(){    }    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);        s1.run();        Student.go();   //静态方法可以直接调用,无需实例化对象        go();    }}
    
    public static void main(String[] args) {        Student student = new Student();        System.out.println("==================");        Student student1 = new Student();    }    // 2    :赋初始值    {        System.out.println("匿名代码块");        //匿名代码块        //随着对象的创建而创建,在构造方法之前    }    // 1    :   只执行一次,后面不会执行    static {        //静态代码快,方便加载初始化一些数据        //随着类的加载而加载,永久只执行一次        System.out.println("静态代码快");    }    // 3    //alt+inset/contorl+return --> select none    public Student() {        System.out.println("构造方法");    }}输出结果:静态代码快匿名代码块构造方法==================匿名代码块构造方法
    

    利用static静态导入包及常量

    //静态导入包import static java.lang.Math.random;import static java.lang.Math.PI;
    

    抽象类和接口

    抽象类

    abstract修饰符可以修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,该类就是抽象类

    抽象类中可以没有抽象方法,但是抽象方法的类一定要声明为抽象类

    抽象类,不能使用new关键字来创建对象,它是用来让子类继承的(类是单继承)

    抽象方法,只有方法的声明,没有方法的实现,它是用来让子类方法去实现的

    子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类

    public  abstract class Action {    //抽象方法,只有方法名字,没有方法的实现    public abstract void doSomething();    //抽象类不能new,只能靠子类去实现    //抽象类可以写普通方法    //抽象类存在构造方法吗?    //抽象类存在的意义?提高开发的可扩展性}//继承抽象类的子类必须重写抽象方法并实现,除非子类也是abstractpublic class A extends Action{    @Override    public void doSomething() {    }}
    

    接口

    声明接口的关键字是interface

    接口可以多继承

    普通类:只有具体的实现

    抽象类:具体实现和规范(抽象方法)都有

    接口:只有规范。约束和实现分离(面向接口编程)

    接口就是规范,定义的是一组规则,体现了现实世界中“如果你是。。。你必须能。。”的思想。如果你是天使你必须能飞,如果你是汽车,你必须能跑。

    接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。

    OO的精髓,是对对象的抽象,最能体现这一点的就是接口。

    //interface 定义的关键字public interface UserService {    //接口中的所有定义其实都是抽象的,不能在接口中实现方法    //修饰符默认为 public abstract    //常量。默认修饰符为 public static final    int AGE = 99;    void add(String name);    void delete(String name);    void update(String name);    void select(String name);}
    
    //实现接口需要重写里面的方法,类可以实现接口//public class 类名(一般以Impl结尾) 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 select(String name) {    }    @Override    public void timer() {    }}
    
    public interface TimeService {    void timer();}
    

    接口小结

    • 接口是一种规范、约束
    • 只有方法的定义,没有方法的实现
    • 方法默认修饰符为public abstract
    • 常量默认修饰符为public static final
    • 接口不能被实例话,接口没有构造方法
    • implements可以实现多个接口
    • 继承接口的类必须重写实现接口的方法

    内部类

    内部类主要分为四种:成员内部类、局部内部类、静态内部类、匿名内部类

    内部类就是在一个类的内部定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。

    成员内部类

    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);        }    }}
    
    public static void main(String[] args) {        Outer outer = new Outer();        outer.out();        //通过外部类实例话内部类:成员内部类        Outer.Inner inner = outer.new Inner();        inner.in();        inner.getID();            }
    

    静态内部类

    静态内部类无法直接访问外部类的非静态属性

    public class Outer {    private int id = 10;    public void out(){        System.out.println("这是外部类的方法");    }    public static class Inner{        public void in(){            System.out.println("这是内部类的方法");        }        //内部类访问外部私有变量        public void getID(){            System.out.println(id);        }    }}
    

    还可以在java文件中声明另一个类

    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);        }    }}//一个java文件里面只能有一个public class,但是可以有多个classclass A{    }
    

    局部内部类

    在类的方法中创建一个类

    public class Outer {    public void method(){            //局部内部类        class Inner{                    }    }}
    

    匿名内部类

    没有类名的内部类

    public class Test {    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("1");    }}interface UserService{    void hello();}
    

    所有内容仅限于维护网络安全学习参考
  • 相关阅读:
    C#之app.config、exe.config和vshost.exe.config作用区别
    C#中decimal ,double,float的区别
    C#中取整,向上取,向下取
    mybatis中的#和$的区别
    mybatis在xml文件中处理大于号小于号的方法
    ORACLE分页查询SQL语法——高效的分页
    移除powerdesigner中Recent Files中无效链接的文件
    Visual Studio提示“无法启动IIS Express Web服务器”的解决方法
    ORA-12638: 身份证明检索失败 的解决办法
    态度决定一切《跟任何人都聊得来》
  • 原文地址:https://www.cnblogs.com/Zh1z3ven/p/14881618.html
Copyright © 2020-2023  润新知