Java学习之面向对象

面向过程

面向过程是一种以事件为中心的编程思想,编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数,这种编程思想即面向过程编程。

面向对象

在日常生活或编程中,简单的问题可以用面向过程的思路来解决,直接有效,但是当问题的规模变得更大时,用面向过程的思想是远远不够的,而且会很繁琐。所以慢慢就出现了面向对象的编程思想。世界上有很多人和事物,每一个都可以看做一个对象,而每个对象都有自己的属性和行为,对象与对象之间通过方法来交互。面向对象是一种以"对象"为中心的编程思想,把要解决的问题分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个对象在整个解决问题的步骤中的属性和行为。

面向对象相关知识点

1. 面向对象与面向过程的比较

A. 面向对象基于面向过程的

B. 相对复杂的事务建议使用面向对象,相对简单的事务适合使用面向过程

2. 类与对象的关系

A. 类是对象的抽取, 对象是类的实例化

B. 属性是一种特征,方法是一种行为

3. 成员变量与局部变量

A. 定义位置, 作用范围,内存位置,生命周期

4. 构造方法

A. 与类同名而没有返回值类型

B. 构造方法可以重载,但是不能被继承

C. 用于创建对象和给对象的属性初始化

5. 代码块

A. 局部代码块:限制变量的生命周期,提高栈内存的利用率

B. 构造代码块:在创建对象的时候先于构造函数执行;用于完成对象的初始化操作

6.匿名对象

指没有名字的对象---只能在创建的时候来使用一次。

如直接new接口,此时会创建一个匿名对象。

7.this

  1. 普通方法中,this总是指向调用该方法的对象。
  2. 构造方法中,this总是指向正要初始化的对象。
  •  this最常的用法:
  1. 让类中的一个方法,访问该类的另一个方法或属性。
  2. 使用this关键字调用重载构造方法。避免相同的初始化代码,只能在构造方法中用,并且必须位于构造方法的第一句。

public class Teacher {

private String name;           

private String gender;  

private int age;

public Teacher(String name){

this(name,"男");

System.out.println("第一行构造器");

public Teacher(String name,String gender ){

this(name,gender,45);

System.out.println("第二行构造器");

}

public Teacher(String name,String gender ,int age){

this.name = name;

this.gender = gender;

this.age = age;

System.out.println("这是第三个构造函数");

}

}

有几点要注意:

  • 1,this只可以调用一个构造器,在一个构造器中不能同时调用两个构造器;
  • 2,必须将你所调用的构造器放在最开始的位置,这也解释了为什么不能在一个构造函数中调用两个构造器,那第二个势必不在最开始位置。
  • 3,本例中在带有两个参数的构造函数中可以用this调用其他任意一个只有一个参数的构造函数,这取决你自己,随便调哪一个都可以。
  • 4,在构造函数之外的方法内不能使用this调用构造函数。代码里面注释的都不能正确编译。

this总结

  • 1、表示对当前对象的引用!
  • 2、表示用类的成员变量,而非函数参数。
  • 3、用于在构造方法中引用满足指定参数类型的构造器(其实也就是构造方法)。但是这里必须非常注意:只能引用一个构造方法且必须位于开始!
  • 4、很明显this不能用在static方法中,因为this指代当前对象,而static则无对象之说。

8. 面向对象的特征

        A. 封装、继承、多态(抽象)

9. 封装

将某些逻辑或者是代码提取成某种对应的形式,这个提取的过程就是封装

体现形式:方法、类、属性的私有化---将属性设置为私有的,然后通过提供对外的方法来获取或者设置这个属性值,在方法中可以限制属性值使之更符合场景要求。

优点:提高代码的复用性,提高代码的安全性(实际上是值得数据的合法性)

简言之主要以下两个要点: 

A. 体现形式:行为的封装---方法; 类的封装---属性的私有化,内部类

B. 优点:复用性,安全性(数据的合法性)

10. 继承

发现一些类中有部分共有的属性和方法,将这些共有的属性和方法提取到了一个新的类中,让这个新的类和原来的类产生联系(关系),这种关系就称之为继承。利用extends关键字产生继承关系。新的类称之为父类(超类,基类),原来的类就称之为子类(派生类)。子类可以通过继承使用父类中的一部分属性和方法。

java中支持的是单继承---一个子类只能有一个父类,但是一个父类可以有多个子类。

java中支持多层继承

单继承和多继承的比较:

多继承在代码的复用性上做的比单继承好。

class A {

        public int m(){

                return 1;

        }

}

class B {

        public int m(){

                return 5;

        }

}

class Demo extends A, B{}

C c = new C();

int i = c.m(); // 如果允许多继承,当存在方法签名一致的方法的时候就会导致调用方法产生歧义

优点:提高代码的复用性,提高代码的安全性(减少方法的调用的混乱)

简言之以下几个要点: 

A. 用extends,单继承

B. 单继承和多继承的优劣性的比较

C. 优点:复用性、安全性(方法调用的混乱问题)

11. 多态

编译时多态:方法的重载。如:

add(2,3)---add(int, int)

add(2,4,6)---add(int, int, int)

运行时多态:方法的重写,向上造型 --- 基于继承 --- 继承是运行时多态的前提

注意:当用向上造型来创建对象的时候能干什么看父类怎么干看子类。---父类规定了有哪些东西可以使用,子类来具体执行

静态代码块

在类中用static{}包起来的代码,就称之为静态代码块。只在类第一次真正使用(指利用这个类创建对象或者调用方法)的时候在栈内存中执行一次。

静态变量可以定义在静态代码块中吗?---不可以

执行顺序:父类静态 -> 子类静态 -> 父类非静态 -> 子类的非静态

简言之主要以下几个要点: 

A. 编译时多态:重载;运行时多态:向上造型和方法的重写---基于继承

B. 行为多态:重载、重写;对象的多态:向上造型

C. 优点:提高代码的灵活性,配合反射完成解耦操作

12. 权限修饰符

A. public protected 默认 private

B. 注意protected和默认权限的修饰范围

同包不同包
修饰符同类子类非子类子类非子类
publicYesYesYesYesYes
protectedYesYesYesYesNo
默认(default)YesYesYesNoNo
privateYesNoNoNoNo

13 super

A. 在子类中表示父类对象的引用,用于调用父类中的方法或者属性

B. super语句:在子类构造函数中调用父类对应形式的构造函数来创建一个父类对象---如果父类中没有无参构造,则子类构造函数中必须手动提供super;super语句必须放在构造函数的第一行

class A {

        public A(int i){}

}

class B extends A{

        public B() {

                super(5);

        }

        public B(int i){

                super(i);

        }

}

14.static 

A. 静态变量。

在类中,用static声明的成员变量为静态成员变量.

可以通过对象引用或类名(不需要实例化)访问静态成员。 

静态变量在类第一次使用的时候加载到了方法区中静态区,并且在静态区赋予了默认值。静态变量是先于对象存在的,所以静态变量可以通过类名来调用。所有的对象共享这个类的静态变量。

B. 静态方法。

随着类第一次使用的时候加载到方法区中的静态区,只是存储在静态区而不执行。在方法被调用的时候到栈内存中执行。静态方法先于对象存在,所以在静态方法中不能直接使用本类中的非静态的属性或者方法。静态方法可以重载,可以被继承,但是不能重写,但是在父子类中可以存在方法签名一致的静态方法---如果父子类中存在了方法签名一致的方法,要么都是静态的,要么都是非静态的。

C.静态代码块。

在类中用static{}包起来的代码,就称之为静态代码块。只在类第一次真正使用(指利用这个类创建对象或者调用方法)的时候在栈内存中执行一次。

静态变量可以定义在静态代码块中吗?---不可以

执行顺序:父类静态 -> 子类静态 -> 父类非静态 -> 子类的非静态

public class StaticDemo {

        public static void main(String[] args) {

                new B();

        }

}

class B {

        public static B b = new B();

        public static int i;

        public static int j = 6;

        static {

                System.out.println("static:");

                System.out.println(i);

                System.out.println(j);

        }

        public B() {

                i++;

                j++;

                System.out.println("Constructor:");

                System.out.println(i);

                System.out.println(j);

        }

}

简言之要点为:

  1. 它为该类的公用变量,属于类,被该类的所有实例共享,在类被载入时被显式初始化,
  2. 对于该类的所有对象来说,static成员变量只有一份。被该类的所有对象共享!!
  3. 可以使用”对象.类属性”来调用。不过,一般都是用“类名.类属性”。
  4. 用static声明的方法为静态方法不需要对象,就可以调用(类名.方法名)
  5. 在调用该方法时,不会将对象的引用传递给它,所以在static方法中不可访问非static的成员。

15. final

A. 常量。定义好之后值不可变

B. 最终方法。 可以重载,可以被继承,不能被重写。

C. 最终类。不能被继承

成员常量定义时给值,静态常量调用时给值。

16. abstract

A. 抽象类。不能实例化(不能创建对象的意思),有构造函数并且构造函数可以私有化,如枚举类就是构造函数私有化的抽象类。抽象类可以含有抽象方法以及实体方法,子类继承抽象类之后必须重写抽象类中的所有的抽象方法,除非这个子类也是抽象类。抽象类一定不是最终类。抽象类中不一定有抽象方法

B. 抽象方法。没有方法体,可以被重载,必须被继承必须被重写。---不能用static/final/private修饰。如果一个抽象方法使用默认权限修饰的,那么要求父子类必须同包。---抽象方法所在的类一定是最终类

17. interface

定义接口的。用implements关键字来让类实现接口。类实现接口之后必须实现接口中所有的抽象方法,除非这个类也是抽象类。java中支持的是多实现。接口和接口之间是多继承。接口不能实例化,也没有构造函数。接口中的方法都是抽象方法(jdk1.7及其以前),接口中的方法默认就是用public abstract修饰。接口中可以定义属性,这个属性默认是用public static final修饰。(JDK1.8之后接口中允许定义实体方法,不过要用default修饰)

作用:同意结构、便于模块化开发。

要点有以下几条:

A. jdk1.7及其以前,接口只能声明抽象方法;从jdk1.8开始,接口中允许定义实体方法

B. 接口与类之间用implements关键字来关联,称之为实现关系。一个类可以实现多个接口,一个接口可以继承多个接口。

C. 接口中的抽象方法默认用public abstract修饰

D. 接口中的属性默认用public static final修饰

E. 作用:统一结构,便于模块化开发

18. 内部类

为什么使用内部类?
使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,
对于内部类都没有影响
使用内部类最大的优点就在于它能够非常好的解决多重继承的问题,使用内部类还能够为我们带来如下特性:
(1)内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独。
(2)在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类
(3)创建内部类对象的时刻并不依赖于外围类对象的创建。
(4)内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
(5)内部类提供了更好的封装,除了该外围类,其他类都不能访问

要点有以下:

A. 方法内部类、成员内部类、静态内部类、匿名内部类

B. 除了静态内部类以外,其他内部类中都不允许定义静态变量和静态方法但是可以定义静态常量

C. 除了静态内部类以外,其他内部类中可以使用当前外部类中的非静态属性和非静态方法

D. 方法内部类在使用当前方法中的数据的时候要求这个数据是一个常量

19.方法内部类

定义在方法中的类---方法内部类

只能在定义它的方法中使用。方法内部类中可以使用当前外部类中的方法和属性,只能使用当前方法中的常量。方法内部类中不能定义静态变量和静态方法,但是可以定义静态常量

   /*

        使用的形参为何要为 final

         在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,

         也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,

         毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解

         和不可接受的,所以为了保持参数的一致性,就规定使用 final 来避免形参的不改变

         */

        public class Outer{

            public void Show(){

                final int a = 25;

                int b = 13;

                class Inner{

                    int c = 2;

                    public void print(){

                        System.out.println("访问外部类:" + a);

                        System.out.println("访问内部类:" + c);

                    }

                }

                Inner i = new Inner();

                i.print();

            }

            public static void main(String[] args){

                Outer o = new Outer();

                o.show();

            }

        }    

方法内部类:访问仅限于方法内或者该作用域内
(1).局部内部类就像是方法里面的一个局部变量一样,是不能有 public、protected、private 以及 static 修饰符的
(2).只能访问方法中定义的 final 类型的局部变量,因为:
当方法被调用运行完毕之后,局部变量就已消亡了。但内部类对象可能还存在,
直到没有被引用时才会消亡。此时就会出现一种情况,就是内部类要访问一个不存在的局部变量;
==>使用final修饰符不仅会保持对象的引用不会改变,而且编译器还会持续维护这个对象在回调方法中的生命周期.
局部内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,
自己内部的方法调用的实际是自己的属性而不是外部类方法的参数;
防止被篡改数据,而导致内部类得到的值不一致

注意:在JDK8版本之中,方法内部类中调用方法中的局部变量,可以不需要修饰为 final,匿名内部类也是一样的,主要是JDK8之后增加了 Effectively final 功能 

反编译jdk8编译之后的class文件,发现内部类引用外部的局部变量都是 final 修饰的

20.成员内部类

定义在类内方法外的类。

成员内部类中可以定义非静态方法和非静态属性不能定义静态变量和静态方法,但是可以定义静态常量。成员内部类可以使用外部类中的方法或者属性---要求能够看懂类外创建内部类对象的方式

成员内部类:

public class Outer{

        private int age = 99;

        String name = "Coco";

        public class Inner{

            String name = "Jayden";

            public void show(){

                System.out.println(Outer.this.name);

                System.out.println(name);

                System.out.println(age);

            }

        }

        public Inner getInnerClass(){

            return new Inner();

        }

        public static void main(String[] args){

            Outer o = new Outer();

            Inner in = o.new Inner();

            in.show();

        }

    }

1.Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,
如 public 、 protected 、 private 等
2方.Inner 类中定义的 show() 法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,
如直接访问 Outer 类中的私有属性age
3.定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,
即:内部类 对象名 = 外部类对象.new 内部类( );
4.编译上面的程序后,会发现产生了两个 .class 文件: Outer.class,Outer$Inner.class{}
5.成员内部类中不能存在任何 static 的变量和方法,可以定义常量:
(1).因为非静态内部类是要依赖于外部类的实例,而静态变量和方法是不依赖于对象的,仅与类相关,
简而言之:在加载静态域时,根本没有外部类,所在非静态内部类中不能定义静态域或方法,编译不通过;
非静态内部类的作用域是实例级别
(2).常量是在编译器就确定的,放到所谓的常量池了
★★友情提示:
1.外部类是不能直接使用内部类的成员和方法的,可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法;
2.如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,
可以使用 this 关键字,如:Outer.this.name

​​​​​​​21.静态内部类

static修饰的内部类

  1. B.m();---如果A是对象,就意味着B是A中的属性,那么m就是一个普通方法;如果A是类,B也是类,那么B就是A的静态内部类,m就是B中的静态方法;如果A是类,而B是对象,那么m就是B对象身上的普通方法

public class Outer{

            private int age = 99;

            static String name = "Coco";

            public static class Inner{

                String name = "Jayden";

                public void show(){

                    System.out.println(Outer.name);

                    System.out.println(name);                  

                }

            }

            public static void main(String[] args){

                Inner i = new Inner();

                i.show();

            }

        }

静态内部类: 是 static 修饰的内部类,
1.静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问
2.如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;
如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员
3.创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名 = new 内部类();

​​​​​​​22.匿名内部类

匿名内部类本质上是继承了对应的类或者是实现了对应的接口---任何一个接口都存在匿名内部类形式。任何一个类只要不是最终类都可以存在匿名内部类形式

  • 总结:
  1. 除了静态内部类,其他三种内部类中都不允许定义静态变量和静态方法,但是都允许定义静态常量
  2. 除了静态内部类,其他三种内部类都可以使用外部类中的非静态属性和非静态方法

扩展:类中可以定义类和接口。接口中可以定义类和接口。---类中定义的接口,接口中定义的类或者接口默认是静态的。

  public class OuterClass {

            public InnerClass getInnerClass(final int   num,String str2){

                return new InnerClass(){

                    int number = num + 3;

                    public int getNumber(){

                        return number;

                    }

                };        /* 注意:分号不能省 */

            }

            public static void main(String[] args) {

                OuterClass out = new OuterClass();

                InnerClass inner = out.getInnerClass(2, "chenssy");

                System.out.println(inner.getNumber());

            }

        }

        interface InnerClass {

            int getNumber();

        }         

匿名内部类:

(1).匿名内部类是直接使用 new 来生成一个对象的引用;

(2).对于匿名内部类的使用它是存在一个缺陷的,就是它仅能被使用一次,创建匿名内部类时它会立即创建一个该类的实例,
该类的定义会立即消失,所以匿名内部类是不能够被重复使用;
(3).使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口;
(4).匿名内部类中是不能定义构造函数的,匿名内部类中不能存在任何的静态成员变量和静态方法;
(5).匿名内部类中不能存在任何的静态成员变量和静态方法,匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法
(6).匿名内部类初始化:使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果

23. 包

A. 声明包用的是package,导入包用的import

B. 注意通配符:* 表示导入当前包下的所有的类而不包括子包下的类

C. java.lang包下的类和同包类不需要导包

24. 垃圾分代回收机制

A. 堆内存分为了新生代和老生代。新生代分为伊甸园区和幸存区。

B. 如果一个对象在新生代放不开会直接放到老生代

C. 初代回收、完全回收

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持不懈的小强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值