Java基础 学习笔记(二)

Java基础 学习笔记(二)

八种基本数据类型

基本类型字节位数默认值取值范围包装类型
byte18(byte)0-128~127Byte
short216(short)0-32768~32767Short
int4320-2147483648 ~ 2147483647Integer
long8640L-9223372036854775808 ~ 9223372036854775807Long
char216‘\u0000’0~65535Character
float4320.0f1.4E-45 ~ 3.4028235E38Float
double8640.0d4.9E-324 ~ 1.7976931348623157E308Double
boolean1falsetrue, falseBoolean

整数的默认类型为int, 浮点数的默认类型为double。

基本数据类型的转换

byte —> short —> int —> long —> float —> double

​ char ----- |

低类型 —> 高类型 可以自动转换

高类型 —> 低类型 需要强制转换,可能会出现数据溢出或精度丢失。

基本数据类型与包装类

Java是面向对象的语言,但基本数据类型却不具有面向对象的特征,当在实际使用中(如,集合中存放Integer类型的对象)需要将基本数据类型包装为对象,便于操作。

包装类均位于java.lang包,其中只有Character和Boolean 的直接父类是Object,其他包装类的直接父类都是Number类(java.lang.Number)。

基本数据类型与包装类型的区别
  • 基本类型有默认值,而包装类型没有赋值就是null
  • 基本类型不可以被用于泛型,而包装类型可以
  • 基本数据类型的局部变量存放在JVM的栈中的局部变量表中,而成员变量(未被static修饰)存放在JVM堆中。包装类型属于对象类型,存在于堆中。
  • 基本数据类型比包装类型占内存空间小。
基本数据类型与包装类型的转换

基本类型——>包装类型, 即装箱

Integer i = new Integer(3); // 使用Integer的构造方法

Integer i = 3; // JDK5后可以自动装箱,实际上是调用了valueOf()

Integer i = Integer.valueOf(3);

Integer的静态方法 valueOf( ) ,参数为基本类型,返回包装类型,如果不需要新的Integer实例对象,则通常应该优先使用该方法,而不是通过构造方法在堆中创建新的对象。valueOf()可以通过缓存经常请求的值(包装类的常量池),而显著提高空间和时间性能。

包装类型——>基本类型 ,即拆箱

int j = i.intValue();

int j = i; // 自动拆箱

String类型———>基本数据类型

Integer.parseInt(String str)

包装类型的常量池

Java为很多基本类型的包装类或字符串都建立常量池,相同的值只存储一份,节省内存,共同访问。在常量池中的这些字符串不会被垃圾收集器回收。

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False

如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。

Integer i = 3; 
// 自动装箱,内部调用valueOf(),即Integer i = Integer.valueOf(3)
int j = 3; // 基本数据类型,常量放在栈内存常量池中
System.out.println(i == j); // true
// 包装类与基本类型比较时,会自动拆箱
Integer k = new Integer(3); // 使用构造器构造对象,在堆中
System.out.println(j == k); // true, k自动拆箱
System.out.println(i == k); // false
// i和k为包装类型对象,使用==时比较的是地址,比较值时使用重写的equals()

面向对象(Object Oriented)

对象就是真实世界的实体,对象与实体是一一对应的,现实世界中的每一个实体都是一个对象。

  • 对象具有属性和行为
  • 具有变化的状态
  • 具有唯一性
  • 对象都是某一个类别的实例
  • 一切皆为对象,真实世界中的所有事物都可以视为对象

把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对有相同属性和行为的对象抽象出其共性,形成类。

面向对象和面向过程的区别

两者的主要区别在于解决问题的方式不同:

  • 面向过程把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题。
  • 面向对象会先抽象出对象(抽象出类,然后通过类实例化对象),然后用对象执行方法的方式解决问题

另外,面向对象开发的程序一般更易维护、易复用、易扩展。

成员变量与局部变量的区别
  • 语法形式:成员变量是属于类的,可以被public, private, static修饰,而局部变量是在方法中定义的变量或参数,不能被访问控制符和static所修饰。但无论是成员变量还是局部变量都能够被final所修饰。
  • 存储方式:局部变量存在于栈中,成员变量被static修饰时,是属于类的,没有static修饰,成员变量是属于实例的。对象存在于堆中。
  • 生存时间:成员变量是对象的一部分,随着对象的创建而存在,局部变量随着方法的调用而自动生成,随着方法的调用结束而消亡。
  • 默认值:员变量如果没有被赋初始值,则会自动以类型的默认值而赋值(一种情况例外:被 final修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。

static关键字

“static方法就是没有this的方法。在static方法内部不能访问非静态方法或变量。反过来是可以的。可以在没有创建任何对象的时候,仅仅通过类本身来调用static方法。”

被static修饰的方法或变量,不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名来访问。方在没有创建任何对象的时候来进行调用。

创建一个对象使用new关键字

new创建对象实例(存在于堆内存中),对象引用(栈中)指向对象实例。

一个对象引用可以指向零或一个对象,一个对象可以有多个引用指向它。

对象相等(内存中存放的内容)不等于对象引用(对象的内存地址)相等。

构造方法

是一种特殊的方法,完成对象的初始化工作。

如果一个类没有声明构造方法,该程序能正确执行吗?

可以执行。一个类没有声明构造方法,会有默认的不带参数的构造方法,当我们new对象时,后边要加一个括号,就是在调用默认的无参构造方法。

构造方法特点:

  • 名字与类名相同
  • 没有返回值,且不能用void声明
  • 不能被重写,但可以被重载,所以可以有一个类多个构造方法

的情况。

面对对象的三大特征

封装,继承,多态

封装

封装是指把一个对象的状态信息隐藏在对象内部,不允许外部访问,但可以提供一些被外界访问的方法来操作属性。

1.把对象的属性和行为看作是一个密不可分的整体,将这两者封装在一个不可分割的独立单元(即对象)中。

2.把不需要外部知道的属性隐藏起来,或某些对象的属性和行为只允许外界用户知道或使用,但不允许更改,而另一些属性或行为不允许外界知道,从而尽可能隐藏对象的功能实现细节。

把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏

封装表现: a. 方法就是一个最基本的封装体 b. 类也是一个封装体

封装的好处: a. 提高了代码的复用性 b. 隐藏了实现细节,还要对外提供可以访问的方式。便于调用者的使用。这是核心之一,也可以理解为就是封装的概念 c. 提高了安全性

继承

子类继承父类的特征和行为,使得子类对象具有父类的实例域和方法,具有父类相同的行为。使用已存在类的定义作为基础建立新类,新类的定义可以增加新的数据或新的功能,但不能选择性继承。可以快速地创建新的类,提高代码的复用,程序的可维护性,节省大量时间,提高开发效率。

继承需要符合的关系是is-a。(如,兔子 is a 动物, 银杏 is a 植物)

继承的好处:

  • 提高了代码的复用性,可维护性,开发效率

  • 使得类与类产生了关系,为多态提供了前提

继承的特性:

  • 子类拥有父类对象所有的属性和方法,包括私有属性和私有方法,但是父类中的private属性和方法,子类无法访问,只是拥有
  • 子类可以拥有自己的属性和方法,即对父类进行扩展。
  • 子类可以用自己的方式实现父类方法(重写)。
  • 继承是单继承,不可以多继承(一个类有多个父类),但是可以多重继承(一个类的父类是另一个类(爷类)的子类)。
  • 继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承object(这个类在 java.lang 包中,所以不需要 import)祖先类。
  • 提高了类之间的耦合性(集成的缺点,耦合度高会造成代码之间的联系越紧密,代码独立性差)。

创建子类对象过程
创建子类

在一个子类对象被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象外部放上子类独有的属性,两者合起来形成一个子类的对象。

在子类的构造方法里,有一行默认的隐式的super( ),即在调用子类构造方法时,父类的构造方法会先执行,因为子类会继承父类中的内容,所以在子类初始化时,必须先去父类中执行初始化动作,才能够使用父类中的内容。当父类中的构造方法是有参的,子类构造方法中必须显示的把 super(参数)写出来
如果子类的构造方法第一行写了this()调用了本类的其他构造方法,那么就本构造方法没有super( )了,因为this( ),super( )只能定义在构造方法的第一行,初始化动作要先执行。
父类的构造方法中,也有隐式的super(),因为所有类都有一个共同父类Object。

子类对象确实拥有父类对象中所有的属性和方法,但是父类对象中的私有属性和方法,子类是无法访问到的,只是拥有,但不能使用。就像有些东西你可能拥有,但是你并不能使用。所以子类对象是绝对大于父类对象的,所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。可以继承,只是无法访问到而已。

多态

1.同一个类中的多态(方法多态),即方法重载,多个方法使用同一个名字,但参数不同,完成的功能不同。

2.不同的类中的多态(对象多态),同一个行为具有多个不同的表现形式,一个对象具有多种的状态,根据其子类的不同完成的功能也不同,重写父类方法,具体表现为父类的引用指向子类的实例

class Animal{
    int age = 1;
    public void barking(){
        System.out.println("animal barking");
    }
}

class Dog extends Animal{
    int age = 2;
    @override
    public void barking(){
        System.out.println("dog barking wangwangwang");
    }
}

class Cat extends Animal{
    int age = 2;
    @override
    public void barking(){
        System.out.println("cat barking miaomiaomiao");
    }
}

public static void main (Sring args[]){
    Animal a = new Dog();  // 父类的引用,指向子类的实例
    a.barking();
    System.out.println(a.age);
    Animal b = new Cat();  // 父类的引用,指向子类的实例
    b.barking();
    System.out.println(b.age);
}

========输出============
    dog barking wangwangwang
    1
    cat barking miaomiaomiao
    1

多态的访问方式:

  • **成员变量,静态方法:编译和运行都看左边。**创建了一个Animal类型的对象,并且使用new Cat()对于这个Animal对象赋值,但最终得到的还是一个Animal类的对象,只需要看“=”左边的Animal a即可。
  • **非静态方法(依赖对象调用):编译看左边,运行看右边。**对象是由子类Dog( ),Cat( )实例化的,从而输出子类中方法重写后的结果。

多态的特点:

  • 对象类型和引用类型之间具有继承(或接口)关系
  • 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定(该引用变量指向哪个类型的对象实例),这样,可以让引用变量绑定到不同的类上实现,调用不同子类的该方法。
  • 向上转型不能调用,只在子类存在但不在父类存在的方法
  • 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法
什么是多态?

多态是面向对象的最后一个主要特征,它本身主要分为两个方面:

  • 方法的多态性:重载与覆写
    重载:同一个方法名称,根据不同的参数类型及个数可以完成不同的功能。
    重写:同一个方法,根据操作的子类不同,所完成的功能也不同。
  • 对象的多态:父子类对象的转换。
    向上转型:子类对象变为父类对象,格式:父类 父类对象 = 子类实例,自动;(Animal a = new Dog();
    向下转型:父类对象变为子类对象,格式:子类 子类对象 = (子类)父类实例,强制。(Dog dog = (Dog)a;
实现多态的方法有哪些?

多态的前提是有父类与子类关系,或实现接口关系。

  • 继承
  • 抽象类与抽象方法
  • 接口
抽象类与抽象方法

一个没有方法体的方法,就是抽象方法。含有抽象方法的类就是抽象类。

// 抽象类定义
abstract class Animal{
    public abstract void barking();  // 抽象方法定义,无方法体
}

// 定义一个子类继承抽象父类
public class Dog extends Animal{
    // 子类必须重写父类中的抽象方法
    @override
    public void barking(){
        System.out.println("dog barking wangwangwang");
    }
}
  • 抽象类可以不含有抽象方法,含有抽象方法的一定是抽象类
  • 抽象类不可以被实例化
  • 抽象类的子类,可以是抽象类,可以是具体的类(必须重写抽象父类中的所有抽象方法)

抽象类除了不能实例化对象,类的其他功能仍存在。所以抽象类必须被继承才能够被使用,故通常在设计阶段决定要不要抽象类。

构造方法,类方法(static修饰) 不能声明为抽象方法。

抽象(abstract)不能与那些关键字共存?
  • prviate,final :修饰时不能被继承,无法被重写。
  • static:static方法需要对方法体执行内容分配空间,而abstract没有方法体。(abstract是没有实现 的,不能产生对象,而是static是属于类的,类本身是已经存在的对象)
  • native:他们本身的定义就是冲突的,native声明的方法是移交本地操作系统实现的,而abstract是移交子类对象实现的,同时修饰的话,导致不知道谁实现声明的方法
接口

是对行为的抽象,是抽象方法的集合,不能被实例化。

一个实现接口的具体类,必须重写接口中的所有抽象方法,否则声明为抽象类。

// 定义一个额外功能的接口
interface extraMethods{
    public static final int legnum = 4;// 值不能改变
    public abstract void sniffer();  // 缉毒
    
    public abstract void guide();  // 导盲
    
}
public class Dog extends Animal implements extraMethods{
    // 子类必须重写父类中的抽象方法
    @override
    public void barking(){
        System.out.println("dog barking wangwangwang");
    }
    
    // 实现了接口的非抽象子类,实现接口中所有抽象方法
    @override
    public void sniffer(){
        System.out.println("dog 缉毒");
    }
    
    @override
    public void guide(){
        System.out.println("dog 导盲");
    }
}

接口中的方法会被隐式的指定为public abstract,变量被指定为 public static final。接口中的方法只能由实现接口的类实现。

接口中的方法均为公共访问的抽象方法 ,接口中无法定义普通的成员变量。
接口与接口之间是继承关系,可以单继承,也可以多继承。

interface A{}
interface B{}
interface C extends A, B{}
抽象类与接口的区别
  • 接口主要用于对类的行为进行约束,实现了某个接口,就拥有了对应的行为能力

  • 一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口 弥补了Java的单继承)

  • 抽象类是这个事物中应该具备的内容,继承体系是一种 is-a关系。 接口是这个事物中的额外内容,继承体系是一种 like-a关系

    class Machine() implements extraMethods{
        // 实现了接口的非抽象子类,实现接口中所有抽象方法
        @override
        public void sniffer(){
            System.out.println("机器 缉毒");
        }
        
        @override
        public void guide(){
            System.out.println("机器 导盲");
        }
        
    }
    

    机器实现了额外功能的接口,就拥有了缉毒和导盲的功能。

二者的选用:

  • 优先选用接口,尽量少用抽象类;
  • 需要定义子类的行为,又要为子类提供共性功能时才选用抽象类。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值