Java 笔试备战

2017-10-16  本文已影响0人  SilenceAK47

面向对象特征: 封装,继承,多态

封装:把属性隐藏,提供公共方法对其访问(private 封装特性的一种)
面向对象举例:利用对象的方法
面向过程:一步一步执行过程


静态变量、静态方法


构造函数

作用:可以用于给对象进行初始化

默认构造函数的访问权限:

默认构造函数的访问权限和所属类一致
即:类被public修饰,那么默认构造函数也带public修饰(private同理)

构造函数与自定义函数区别:

写法上:

  • 构造函数-无返回值
  • 自定义函数-返回值可有可无

调用时机:

  • 构造函数-对象创建是调用
  • 自定义函数-由实例对象调用

main方法


final关键字

final在Java中是一个保留的关键字,可以声明成员变量、方法、类以及本地变量。一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误

final变量

只能赋值一次即可修饰成员变量,也可修饰局部变量

final变量经常和static关键字一起使用,作为常量。

final方法

方法前面加上final关键字,代表这个方法不可以被子类的方法重写。

如果你认为一个方法的功能已经足够完整了,子类中不需要改变的话,你可以声明此方法为final。final方法比非final方法要快,因为在编译的时候已经静态绑定了,不需要在运行时再动态绑定。

final类

final类通常功能是完整的,它们不能被继承,被子类复写功能

Java中有许多类是final的,譬如String, Interger以及其他包装类。

final优点
  1. final关键字提高了性能。JVM和Java应用都会缓存final变量。
  2. final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
  3. 使用final关键字,JVM会对方法、变量及类进行优化。
final的重要知识点
  1. final关键字可以用于成员变量、本地变量、方法以及类。
  2. final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。
    你不能够对final变量再次赋值。
  3. final本地变量必须在声明时赋值。
  4. 在匿名类中所有变量都必须是final变量。
  5. final方法不能被重写。
  6. final类不能被继承。
  7. final关键字不同于finally关键字,后者用于异常处理。
  8. final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
  9. 接口中声明的所有变量本身是final的。
  10. final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
  11. final方法在编译阶段绑定,称为静态绑定(static binding)。
  12. 没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
  13. 将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
  14. 按照Java代码惯例,final变量就是常量,而且通常常量名要大写

抽象类

在了解抽象类之前,先来了解一下抽象方法

抽象方法是一种特殊的方法,它只有声明,而没有具体的实现。

抽象方法的声明格式为:

abstract void fun(); // 抽象方法必须用abstract关键字进行修饰

如果一个类含有抽象方法,则称这个类为抽象类

  • 抽象类必须在类前用abstract关键字修饰
  • 抽象类可以有构造函数(子类创建对象前被调用),但不能用抽象类创建对象,因为抽象类中含有无具体实现的方法
  • 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public
  • 如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类

在其他方面,抽象类和普通的类并没有区别(可以拥有成员变量和普通的成员方法)。


接口

接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是对行为的抽象。在Java中,定一个接口的形式如下:

[public] interface InterfaceName {
}

接口中可以含有 变量和方法。但是要注意:

  • 接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误)
  • 方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法

从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加“抽象”,并且一般情况下不在接口中定义变量。

要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下:

class ClassName implements Interface1,Interface2,[....]{
}

可以看出:

  • 允许一个类遵循多个特定的接口
  • 如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法

抽象类和接口的区别

语法层面上的区别
  1. 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
  3. 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
  4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口
  5. 抽象类不能被实例化,但可以有构造方法,接口中不能有构造方法
设计层面上的区别

详情请见


单例模式

单例的实现
  1. 构造函数权限 private
  2. 对象是static属性 (保证内存只存一份)
  3. 接口 static

继承

如何使用继承体系中的功能
  • 要使用体系,首先查阅体系父类的描述,因为父类中定义的是该体系中"共性功能"
  • 通过了解共性功能,就可以知道该体系的基本功能。
为什么在具体调用时,要创建最子类的对象?
  • 可能是因为父类不能创建对象
  • 创建子类对象可以使用更多的功能,包括父类的+自己特有的

重写(也称覆盖)


多态

多态指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

举个例子:

比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。

多态存在的三个必要条件
  1. 要有继承
  2. 要有重写
  3. 父类引用指向子类对象
多态的好处
  1. 可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作
  2. 可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性
  3. 接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的
  4. 灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
  5. 简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

内部类

内部类访问格式

当内部类定义在外部类的成员位置上,且非私有。创建内部类的格式:

外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Inter inter = new Outer.new Inter();

内部类定义在局部时:
  1. 不可以被成员修饰符修饰
  2. 可以直接访问外部类中的成员 //因为持有外部类中的引用
  3. 不可以访问它所在的局部中变量。只能访问被final修饰的局部变量

异常

严重问题Error类
非常严重问题Exception类

Throwable

Error

RuntimeException
Exception

异常信息打印
  • e.getMessage() //打印异常信息
  • e.toString() //异常名称+异常信息
  • e.printStackTrace() //异常名称,异常信息,异常出现的位置(jvm默认异常处理机制就是调用 printStackTrace())

集合

List

有序,可重复

Set

无序,不可重复

Map

无序,key不可重复,value可重复


Iterator遍历的添加、删除

// 添加
List list = new ArrayList<String>();
Iterator it = list.iterator();
List<String> newList = new ArrayList<String>();
while(it.hasNext){
     Object obj = it.next;
     if(obj.equals('5')){
         newList.add(obj);
     }
}
list.addAll(newList)
// 删除
List list = new ArrayList<String>();
Iterator it = list.iterator();
while(it.hasNext){
     Object obj = it.next;
     if(obj == '5'){
         it.remove();
     }
}

加载顺序

静态变量、静态块——>main方法——>成员变量(匿名块属于成员变量)——>构造方法——>方法(静态、非静态)

同级的加载顺序由编写先后决定

public class test {                         //1.第一步,准备加载类

    public static void main(String[] args) {
        new test();                         //4.第四步,new一个类,但在new之前要处理匿名代码块        
    }

    static int num = 4;                    //2.第二步,静态变量和静态代码块的加载顺序由编写先后决定 

    {
        num += 3;
        System.out.println("b");           //5.第五步,按照顺序加载匿名代码块,代码块中有打印
    }

    int a = 5;                             //6.第六步,按照顺序加载变量

    { // 成员变量第三个
        System.out.println("c");           //7.第七步,按照顺序打印c
    }

    test() { // 类的构造函数,第四个加载
        System.out.println("d");           //8.第八步,最后加载构造函数,完成对象的建立
    }

    static {                              // 3.第三步,静态块,然后执行静态代码块,因为有输出,故打印a
        System.out.println("a");
    }

    static void run()                    // 静态方法,调用的时候才加载// 注意看,e没有加载
    {
        System.out.println("e");
    }
}

存在继承关系时的加载顺序

public class Print {

     public Print(String s){
         System.out.print(s + " ");
     }
 }
public class Parent{

     public static Print obj1 = new Print("1");

     public Print obj2 = new Print("2");

     public static Print obj3 = new Print("3");

     static{
         new Print("4");
     }

     public static Print obj4 = new Print("5");

     public Print obj5 = new Print("6");

     public Parent(){
         new Print("7");
     }

 }
public class Child extends Parent{

     static{
         new Print("a");
     }

     public static Print obj1 = new Print("b");

     public Print obj2 = new Print("c");

     public Child (){
         new Print("d");
     }

     public static Print obj3 = new Print("e");

     public Print obj4 = new Print("f");

     public static void main(String [] args){
         Parent obj1 = new Child ();
         Parent obj2 = new Child ();
     }
 }

执行main方法,程序输出顺序为: 1 3 4 5 a b e 2 6 7 c f d 2 6 7 c f d
输出结果表明,程序的执行顺序为:
如果类还没有被加载:

1、先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关。
2、执行子类的静态代码块和静态变量初始化。
3、执行父类的实例变量初始化
4、执行父类的构造函数
5、执行子类的实例变量初始化
6、执行子类的构造函数

如果类已经被加载:

则静态代码块和静态变量就不用重复执行,再创建类对象时,只执行与实例相关的变量初始化和构造方法。


网络编程

UDP

将数据及源和目的封装在数据包中,区需要建立连接
每个数据报的大小限制在64K内
因无连接,是不可靠协议
不需要建立连接,速度快

TCP

建立连接,形成传输数据的通道
在连接中进行大数据量传输
三次握手,是可靠协议
必须建立连接,效率会稍低


  1. 之所以不允许静态方法访问实例成员变量,是因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以它也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this`

上一篇 下一篇

猜你喜欢

热点阅读