深入理解Java基础(一)

您所在的位置:网站首页 方法的重载和静态成员 深入理解Java基础(一)

深入理解Java基础(一)

#深入理解Java基础(一)| 来源: 网络整理| 查看: 265

1、面向对象的三大特性

1、封装把对象的属性操作等隐藏起来,保留对外的接口,用户通过接口来访问这个对象。优点:

提高安全性可重用减少耦合

2、继承继承就是子类继承父类的特征和行为。

子类继承父类的所有属性和方法,但是父类中的私有方法子类无法访问,只是拥有。子类可以拥有自己的属性和方法,对父类进行扩展。子类可以用自己的方式去实现父类的方法。Java不支持多重继承,但一个类可以实现多个接口,从而克服单继承的缺点;

优点:通过继承可以快速创建新的类,实现代码的重复利用,提高开发的效率。 super关键字使用 super可以访问父类成员属性,成员方法,构造方法。 super.父类成员变量 super.成员方法名(); super();//父类构造方法

访问父类的构造函数: 可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作。访问父类的成员: 如果子类重写了父类的中某个方法的实现,可以通过使用 super 关键字来引用父类的方法实现。

3、多态是指同一行为,对于不同的对象具有多个不同表现形式。多态分为编译时多态和运行时多态:

编译时多态主要指方法的重载

编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的方法。通过编译之后会变成两个不同的方法

运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定运行时多态有三个条件:

1、继承 2、重写 3、向上转型

继承:在多态中必须存在有继承关系的子类和父类。重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。

只有满足这 3 个条件,开发人员才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而执行不同的行为。

2、八大基本数据类型

(1)整数类型:byte、short、int、long(2)小数类型:float、double(3)字符类型:char(4)布尔类型:boolean

byte:1个字节,8位,256种状态,取值范围为【-128,127】short:2个字节,16位,65536种状态,取值范围为【-32768,32767】int:4个字节,32位,整数类型默认是int类型,取值范围约21亿long:8个字节,64位,long类型表示long类型常量,要加L或者l,建议加Lfloat:4个字节,32位,单精度,能精确到6~7位,声明一个小数类型,要加F或者f,建议加Fdouble:8个字节,64位,双精度,能精确到15~16位,小数类型默认是double类型char:2个字节,16位,字符表示Unicode(万国码)编码表中的每一个符号,每个符号使用单引号引起来,其中前128个符号和ASCII表相同char:2个字节,16位,字符表示Unicode(万国码)编码表中的每一个符号,每个符号使用单引号引起来,其中前128个符号和ASCII表相同

3、缓存池

是一种降低磁盘访问的机制。new Integer(123) 与 Integer.valueOf(123) 的区别在于:

new Integer(123) 每次都会新建一个对象Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。 Integer x = new Integer(123); Integer y = new Integer(123); System.out.println(x == y); // false Integer z = Integer.valueOf(123); Integer k = Integer.valueOf(123); System.out.println(z == k); // true

1.Integer的缓存池大小为一个字节,也就是(-128~127)。 2.valueOf()方法会首先判断参数是否存在于缓存池对象中,若存在,则引用并返回该对象,引用同一个对象时,它们的地址是一样的,因此用 == 去比较,则返回结果为true。 3.若参数不能在缓存池中找到对应对象,则会new一个包装类对象,每次new的对象地址是不同的,因此用 == 去比较它们返回false。

4、String

String 类型被声明为final ,不可以被继承String不可以改的原因:1、内部使用char[]存储数据,该数组被声明为final2、String内部没有提供更改value数组的方法 String不可变的好处

可以缓存 hash 值 (String 用做 HashMap 的 key)String Pool 的需要

如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool

安全性线程安全

可以在多个线程中安全地使用 String, StringBuffer and StringBuilder 对比1、String 不可变 | StringBuffer、StringBuilder 可变2、String线程安全 | StringBuffer线程安全(内部使用synchronized进行同步)、 StringBuilder线程不安全 String.intern()使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象。(指向同一个对象)

String s1 = new String("aaa"); String s2 = new String("aaa"); System.out.println(s1 == s2); // false String s3 = s1.intern(); System.out.println(s1.intern() == s3); // true //intern() 首先把 s1 引用的对象放到 String Pool(字符串常量池)中,然后返回这个对象引用。 //因此 s3 和 s1 引用的是同一个字符串常量池的对象。 String s4 = "bbb"; String s5 = "bbb"; System.out.println(s4 == s5); // true //如果是采用 "bbb" 这种使用双引号的形式创建字符串实例,会自动地将新建的对象放入 String Pool 中。

字符串拼接使用+还是使用Stringbuilder? 都可以,字符串使用+进行拼接时是通过Strig builder调用append()实现,拼接完成后调用toString().但是如果在循环内部使用 + 拼接,每循环一次就会创建一个StringBuilder对象。直接使用 StringBuilder 对象进行字符串拼接的话,就不会存在这个问题了。

String[] arr = {"he", "llo", "world"}; StringBuilder s = new StringBuilder(); //只有一个StringBuilder对象 for (String value : arr) { s.append(value); } System.out.println(s);

String中的equals() 和 Object中的equals()有什么区别?String 中的 equals 方法是被重写过的,比较的是 String 字符串的值是否相等。 Object 的 equals 方法是比较的对象的内存地址。

字符串常量池字符串常量池是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。

/ 在堆中创建字符串对象”ab“ // 将字符串对象”ab“的引用保存在字符串常量池中 String aa = "ab"; // 直接返回字符串常量池中字符串对象”ab“的引用 String bb = "ab"; System.out.println(aa==bb);// true

5、参数传递

Java 的参数是以值传递的形式传入方法中,而不是引用传递。

实参(实际参数,Arguments) :用于传递给函数/方法的参数,必须有确定的值。形参(形式参数,Parameters) :用于定义函数/方法,接收实参,不需要有确定的值。

值传递 :方法接收的是实参值的拷贝,会创建副本 (Java)引用传递 :方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参。(C++)

6、Switch

Java 7 中switch开始支持String

String s = "a"; switch (s) { case "a": System.out.println("aaa"); break; case "b": System.out.println("bbb"); break; }

switch 不支持 long字符串的 switch 是通过equals()和hashCode()方法来实现的。

7、抽象类和接口

抽象类和抽象方法都使用 abstract 关键字进行声明。抽象类一般会包含抽象方法,抽象方法一定位于抽象类中。抽象类和普通类最大的区别是,抽象类不能被实例化,需要继承抽象类才能实例化其子类。 抽象类和接口的区别共同点:

都不能被实例化。都可以包含抽象方法。都可以有默认实现的方法(Java 8 可以用 default 关键字在接口中定义默认方法)。

不同点:

1. 一个类只能继承一个类,但是可以实现多个接口 2. 接口中的成员变量只能是 public 、static 、final 类型的,不能被修改且必须有初始值,而抽象类的成员变量默认 default,可在子类中被重新定义,也可被重新赋值。 3. 接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。抽象类主要用于代码复用,强调的是所属关系。

8、重写与重载

1、重写存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。为了满足里式替换原则,重写有以下两个限制:

子类方法的访问权限必须大于等于父类方法;子类方法的返回类型必须是父类方法返回类型或为其子类型。

使用 @Override 注解,可以让编译器帮忙检查是否满足上面的两个限制条件。2、重载存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。应该注意的是,返回值不同,其它都相同不算是重载。

9、equals() 与 ==

1、等价关系

//等价关系 //自反性 x.equals(x); // true //对称型 x.equals(y) == y.equals(x); // true //传递性 if (x.equals(y) && y.equals(z)) x.equals(z); // true; //一致性 多次调用 equals() 方法结果不变 x.equals(y) == x.equals(y); // true //与 null 的比较 对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false x.equals(null); // false;

2、equals()与 ==

对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。对于引用类型,== 判断两个变量是否引用同一个对象(对象的内存地址),而 equals() 判断引用的对象是否相等。 10、hashcode()

hashCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。 Java 中的任何类都包含有 hashCode() 函数其实, hashCode() 和 equals()都是用于比较两个对象是否相等。 为什么 JDK 还要同时提供这两个方法呢?在一些容器(比如 HashMap、HashSet)中,有了 hashCode() 之后,判断元素是否在对应容器中的效率会更高为什么不只提供 hashCode() 方法呢?因为两个对象的hashCode 值相等并不代表两个对象就相等。 为什么两个对象有相同的 hashCode 值,它们也不一定是相等的?因为 hashCode() 所使用的哈希算法也许刚好会让多个对象传回相同的哈希值。 为什么重写 equals() 时必须重写 hashCode() 方法?因为两个相等的对象的 hashCode 值必须是相等。也就是说如果 equals 方法判断两个对象是相等的,那这两个对象的 hashCode 值也要相等。如果重写 equals() 时没有重写 hashCode() 方法的话就可能会导致 equals 方法判断是相等的两个对象,hashCode 值却不相等。 总结:

如果两个对象的hashCode 值相等,那这两个对象不一定相等(哈希碰撞)。如果两个对象的hashCode 值相等并且equals()方法也返回 true,我们才认为这两个对象相等。如果两个对象的hashCode 值不相等,我们就可以直接认为这两个对象不相等。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3