自我参考-Java面向对象(上)

一、类和对象
1.对象
  随处可见的一种事物就是对象,对象是事物存在的实体。人们思考这些对象都是由何种部分组成的,通常会将对象划分为动态部分和静态部分。静态部分,顾名思义,就是不能动的部分,这部分被称为“属性”,任何对象都会具备其自身属性。一个人具备的行为行动,就是动态部分。
2.类
  类就是同一类事物的统称,对象是类的实例。如果将现实世界中的一个事物抽象成对象,类就是这类对象的统称。类是构造对象时所以来的规范,具有相同特性和行为的一类事物就称为类,类的思想就是这么产生的。更为恰当地描述是:类是世间事物的抽象称呼,而对象则是这个事物相对应的实体,如果面临实际问题,通常需要实例化类对象来解决。
  类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。
  在Java语言中,类中对象的行为是以方法的形式定义的,对象的属性是以成员变量的形式定义的,而类包括对象的属性和方法。

  • 同一类事物的统称;
  • 封装一类事物的属性和行为的载体
  • 对象是类的实例
  • 通过类来生成对象

二、方法详解
1. 工厂模式
  为了解决多个类似对象声明的问题,可以使用一种叫做工厂模式的方法,这种方法就是为了解决实例化对象产生大量重复的问题
问题:工厂模式解决了重复实例化的问题,但还有一个问题,就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。
2. 构造函数模式
  使用了构造函数的方法,和使用工厂模式的方法他们不同之处如下:

  • 构造函数方法没有显示的创建对象(new Object());
  • 直接将属性和方法赋值给 this 对象;
  • 没有 renturn 语句。

构造函数的方法有一些规范:

  • 函数名和实例化构造名相同且大写,(PS:非强制,但这么写有助于区分构造函数和普通函数);
  • 通过构造函数创建对象,必须使用 new 运算符。
  • 原型模式
  • 混合构造函数和原型模式
  • 动态原型模式
  • 寄生构造函数模式
  • 稳妥构造函数模式

三、成员变量、局部变量和变量
1、成员变量与局部变量的区别

  • 成员变量:
    • 成员变量定义在类中,在整个类中都可以被访问。
    • 成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中。
    • 成员变量有默认初始化值。
  • 局部变量:
    • 局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效。
    • 局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
    • 局部变量没有默认初始化值

在使用变量时需要遵循的原则为:就近原则:首先在局部范围找,有就使用;接着在成员位置找。

2、成员变量和类变量的区别
  由static修饰的变量称为静态变量,其实质上就是一个全局变量。如果某个内容是被所有对象所共享,那么该内容就应该用静态修饰;没有被静态修饰的内容,其实是属于对象的特殊描述。
  不同的对象的实例变量将被分配不同的内存空间, 如果类中的成员变量有类变量,那么所有对象的这个类变量都分配给相同的一处内存,改变其中一个对象的这个类变量会影响其他对象的这个类变量,也就是说对象共享类变量。

3、成员变量和类变量的区别:

  • 两个变量的生命周期不同
    • 成员变量随着对象的创建而存在,随着对象的回收而释放。
    • 静态变量随着类的加载而存在,随着类的消失而消失。
  • 调用方式不同
    • 成员变量只能被对象调用。
    • 静态变量可以被对象调用,还可以被类名调用。
  • 别名不同
    • 成员变量也称为实例变量。

4)数据存储位置不同
  成员变量存储在堆内存的对象中,所以也叫对象的特有数据。
  静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据。
4、成员变量与静态变量比较

  • 成员变量所属于对象。所以也称为实例变量。
    静态变量所属于类。所以也称为类变量。
  • 成员变量存在于堆内存中。
    静态变量存在于方法区中。
  • 成员变量随着对象创建而存在。随着对象被回收而消失。
    静态变量随着类的加载而存在。随着类的消失而消失。

4)成员变量只能被对象所调用 。
  静态变量可以被对象调用,也可以被类名调用。
  所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
  
四、隐藏和封装
  封装就是用类来管理属性和方法;隐藏就是把属性或方法声明为私有。

封装原则:将不需要对外提供的内容都隐藏起来;把属性都隐藏,提供公共方法对其访问。

  Java中可以通过对类的成员设置一定的访问权限,实现类中成员的信息隐藏。

  • private:类中限定为private的成员,只能被这个类本身访问。如果一个类的构造方法声明为private,则其它类不能生成该类的一个实例。
  • default:类中不加任何访问权限限定的成员属于缺省的(default)访问状态,可以被这个类本身和同一个包中的类所访问。
  • protected:类中限定为protected的成员,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问。
  • public:类中限定为public的成员,可以被所有的类访问。

五、深入构造器
  构造器是创建Java对象的重要途径,通过 new关键字来调用构造器,构造器也确实返回了该类的对象,但是这个对象并不是完全由构造器来负责创建的。实际上,当程序员调用构造器时,系统会为该对象分配内存控件,并为这个对象执行默认初始化,如果这个对象已经产生了,那么这些操作在执行构造器之前就已经都完成了。
  所以说当系统开始构造器的执行体之前,系统已经创建了一个对象,只是这个对象还不能够被外界程序访问,只能在该构造器中通过 this来引用。当构造器的执行体结束后,这个对象作为构造器的返回值被返回,通过赋值给另一个引用类型的变量,从而让外部程序访问。

六、类的继承、多态

  • 继承。
    • 在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法(Override,重写方法)使之更适合特殊的需要,这就是继承。
    • 继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。继承的优点是子类可以重写父类的方法来方便地实现对父类的扩展。
  • 多态。
    • 多态是运行时刻接口匹配的对象相互替换的能力。
    • 指程序定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编译期并不确定,而是在程序运行期间才确定(称之为动态绑定),即一个引用变量指向的是哪个类的实例对象,在编译期间并不确定,在运行阶段才能决定,因此,这样就可以使得引用变量绑定到各种不同的类实现上,从而实现不同的行为。
    • 多态性增强了软件的灵活性和扩展性。

七、继承与组合
  组合与继承都是提高代码可重用性的手段。
  在设计对象模型时,可以按照语义来识别类之间的组合关系和继承关系。在有些情况下,采用组合关系或者继承关系能完成同样的任务,组合和继承存在着对应关系:组合中的整体类和继承中的子类对应,组合中的局部类和继承中的父类对应,如下图:

  • 组合
    组合
  • 继承
    这里写图片描述

继承与组合的优缺点

组合关系继承关系
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
优点:具有较好的可扩展性缺点:支持扩展,但是往往以增加系统结构的复杂度为代价
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象缺点:不支持动态继承。在运行时,子类无法选择不同的父类
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口缺点:子类不能改变父类的接口
缺点:整体类不能自动获得和局部类同样的接口优点:子类能自动继承父类的接口
缺点:创建整体类的对象时,需要创建所有局部类的对象优点:创建子类的对象时,无须创建父类的对象



八、初始化块
  Java使用构造器来对单个对象进行初始化操作,使用构造器先完成整个Java对象的状态初始化,然后将Java对象返回给程序,从而让该Java对象的信息更加完整。与构造器作用非常类似的是初始化块,它也可以对Java对象进行初始化操作
  一个类里可以有多个初始化块,相同类型的初始化块之间有顺序:前面定义的初始化块先执行,后面定义的初始化块执行

[修饰符]  {
        //初始化块的可执行性代码
        。。。
}

  初始化块的修饰符只能是static,使用static修饰的初始化块被称为静态初始化。初始化块里的代码可以包含任何可执行性语句,包括定义局部变量 ,调用其他对象的方法,以及使用分支,循环语句等
下面定义一个初始化块也有构造器

public class Person {
{//定义第一个初始化块
  int a= 6;//初始化块中
  if (a >4){
    System.out.println("Person初始化块:局部变量a的值大于4");
  }
  System.out.println("Person的初始化块");
}

//定义第二个初始化块
{
System.out.println("Person 的第二个初始化块");
}
//定义无参数的构造器
public Person(){
  System.out.println("Person类的无参数构造器");
}
public static void main(String[] args){
  new Person();
}
}

九、初始化块和构造器
  从某种程度上来看,初始化块是构造器的补充,初始化块总是在构造器执行之前执行。
  初始化块跟构造器不同的是初始化块是一段固定执行的代码,他不能接收任何参数。
  通过把多个构造器中的相同代码提取到初始化块中定义,能更好地提高初始化代码的复用,提高整个应用的可维护性。
  与构造器类似,创建一个Java对象时,不仅会提高该类的图片初始化块和构造器,而且系统会一直上朔到Java.lang.Object类,先执行该类的初始化块,开始执行该类的构造器,一次向下执行器父类的初始化块,开始执行其父类的构造器,最后才执行该类的初始化块和构造器,返回该类的对象。
  
  静态初始化块
  如果定义初始化块时使用了static修饰符,则这个初始化块就变成了静态初始化块,也被称为类初始化块。静态初始化块是类相关的,系统将在类初始化阶段执行静态初始化块,而不是在创建对象时才执行。因此静态初始化块总是比普通初始化块先执行。
  静态初始化块是类相关的,用于对整个类进行初始化处理,通常用于对类Field执行初始化处理,静态初始化块不能对实例Field进行初始化处理。
  静态初始化块也被称为类初始化块,也属于类的静态成员,同样需要遵循静态成员不能访问非静态成员的规则,因此静态初始化块不能访问非静态成员,包括访问实例Field和实例方法。
  与普通初始化块类似的是,系统在类初始化阶段执行静态初始化块时,不仅会执行本类的静态初始化块,而且还会一直上朔到java.lang.Object了,先执行java.lang.Object类的静态初始化块,然后执行父类的静态初始化块,最后才执行该类的静态初始化块,经过这个过程,才完成了该类的初始化过程。只有当类初始化完成后,才可以在系统中使用这个类,包括访问这个类的类方法-类Field,或者用这个类来创建实例。

十、java8增强的包装类
  自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)功能

package code;
public class AutoBoxUnboxing{
    public static void main(String [] args){
        // 直接把一个基本类型变量赋给Integer对象
        Integer inObj = 5;     
        // 直接把一个boolean类型变量赋给一个Object类型的变量
        Object boolObj = true;
        // 直接把一个Integer对象赋给int类型的变量  
        int it = inObj;         
        if(boolObj instanceof Boolean){
            // 先把Object对象强制类型转换为Boolean类型,再赋给boolean变量
            boolean b = (Boolean)boolObj;  
            System.out.println(b);
        }
    }
}

  当JDK提供了自动装箱和自动拆箱功能后,大大简化了基本类型变量和包装类对象之间的转换过程
  把字符串类型的值转换为基本类型的值有两种方式:

  • 利用包装类提供的parseXxx(String s )的静态方法,(除了Character);
  • 利用包装类提供的Xxx(String s )构造器

将基本类型变量转换为字符串:

利用String类提供的多个重载valueOf()方法

package code;
public class Primitive2String{
    public static void main(String[] args){
        String intStr = "123";
        // 把一个特定字符串转换成int类型
        int it1 = Integer.parseInt(intStr);  
        int it2 = new Integer(intStr);
        System.out.println(it1);
        System.out.println(it2);

        String floatStr = "4.56";
        float ft1 = Float.parseFloat(floatStr);
        float ft2 = new Float(floatStr);
        System.out.println(ft1);
        System.out.println(ft2);

        String ftStr = String.valueOf(2.345f);
        System.out.println(ftStr);

        // 把一个boolean变量转换成String变量
        String boolStr = String.valueOf(true);  
        System.out.println(boolStr.toUpperCase());
    }
}

  如果希望将基本类型装换成字符串,直接将基本类型和”“进行连接运算,系统会自动把基本类型变量转换成字符串。

package code;
public class WrapperClassCompare{
    public static void main(String[]args){
        Integer a = new Integer(6);
        System.out.println("6的包装类实例是否大于5.0" + (a > 5.0));

        System.out.println("比较两个包装类的实例是否相等" + (new Integer(2) == new Integer(2)));

        //通过自动装箱,允许把基本类型赋值给包装类实例
        Integer ina = 2;
        Integer inb = 2;
        System.out.println("两个2自动装箱后是否相等:" + (ina == inb));//true
        Integer biga = 128;
        Integer bigb = 128;
        System.out.println("两个128自动装箱后是否相等:" + (biga == bigb));//false

        //两个boolean类型比较时,true>false
        System.out.println(Boolean.compare(true,false));
        System.out.println(Boolean.compare(true,true));
        System.out.println(Boolean.compare(false,true));
    }
}

  系统把一个-128~127之间的整数自动装箱成Integer实例,并放入一个名为cache的数组中缓存起来,如果以后把-128~127之间的整数自动装箱成一个Integer实例时,实际上是直接指向对应的数组元素,所以全部相等,但每次把一个不在-128~127范围内的整数自动装箱成Integer实例时,系统总是重新创建一个Integer实例,所以出现上述结果

package code;
public class UnsignedTest{
    public static void main(String[]args){
        byte b = -3;
        //将byte类型的-3转换为无符号整数
        System.out.println("byte类型的-3对应的无符号整型是" + Byte.toUnsignedInt(b));
        //指定使用十六进制解析无符号整数
        int val = Integer.parseUnsignedInt("ab", 16);
        System.out.println(val);
        //将-12转换为无符号int型,然后转换为十六进制的字符串
        System.out.println(Integer.toUnsignedString(-12,16));
        //将两个数转换为无符号整数后相除
        System.out.println(Integer.divideUnsigned(-4,2));
        //将两个数转换为无符号整数相除后求余
        System.out.println(Integer.remainderUnsigned(-2,7));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值