《Java核心技术》——读书笔记

2021-10-09  本文已影响0人  廖少少

Java

Java核心技术第十版源码:https://github.com/deyou123/corejava

与C++的不同

数据类型

浮点类型

特殊值

强制类型转换

二元赋值的强制类型转换

条件运算符、三元运算符

位运算符

枚举类型

enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE};

字符串

子串

拼接

不可变字符串(与C/C++有较大差异)

检测字符串是否相等

空串与Null串

码点与代码单元

Java API

java.lang.String

如果某个方法是在这个版本之后添加的,就会给出一个单独的版本号。

StringBuilder类

读取输入

Scanner类定义在java.util包中。当使用的类不是定义在基本java.lang包中时,一定要使用import指示字将相应的包加载进来

因为输入是可见的,所以Scanner类不适用于从控制台读取密码。Java SE 6特别引入了Console类实现这个目的

java.util.Scanner 5.0

文件输入与输出

控制流程

块作用域

switch语句

中断控制流程语句

大数值

API java.math.BigInteger 1.1

java.math.BigInteger 1.1

数组

foreach循环

数组拷贝

命令行参数

数组API

java.util.Arrays 1.2

多维数组

不规则数组

对象和类

在Java中,只有基本类型(primitive types)不是对象,例如,数值、字符和布尔类型的值都不是对象。
所有的数组类型,不管是对象数组还是基本类型的数组都扩展了Object类。

OOP与类

对象与对象变量

更改器方法与访问器方法

构造器

隐式参数与显式参数

final实例域

static静态域

静态常量

静态方法

C++注释

静态工厂

main方法

方法参数

对象构造

重载

默认域初始化

无参/默认构造方法

显式域初始化

参数名

构造器调用另一个构造器

对象析构与finalize方法

包(package)

导入

静态导入

将类放入包中

包作用域

类设计技巧

  1. 一定要保证数据私有

  2. 一定要对数据初始化

  3. 不要在类中使用过多的基本类型

  4. 不是所有的域都需要独立的域访问器和域更改器

  5. 将职责过多的类进行分解

  6. 类名和方法名要能够体现它们的职责
    命名类名的良好习惯是采用一个名词(Order)、前面有形容词修饰的名词(RushOrder)或动名词(有“-ing”后缀)修饰名词(例如,BillingAddress)。对于方法来说,习惯是访问器方法用小写get开头(getSalary),更改器方法用小写的set开头(setSalary)。

  7. 优先使用不可变的类

继承

超类与子类

覆盖(override)

子类构造器

多态

理解方法调用(重要!)

阻止继承:final类和方法

强制类型转换

抽象类

受保护访问

Object: 所有类的超类

equals方法

equals: 相等测试和继承

hashCode方法

toString方法

泛型数组列表

访问数组列表元素

- `void set(int index,E obj)`

    设置数组列表指定位置的元素值,这个操作将覆盖这个位置的原有内容。
    参数:index 位置(必须介于0~size()-1之间)
    obj 新的值

- `E get(int index)`

    获得指定位置的元素值。
    参数:index 获得的元素位置(必须介于0~size()-1之间)

- `void add(int index,E obj)`

    向后移动元素,以便插入元素。
    参数:index 插入位置(必须介于0~size()-1之间)
    obj 新元素

- `E remove(int index)`

    删除一个元素,并将后面的元素向前移动。被删除的元素由返回值返回。
    参数:index 被删除的元素位置(必须介于0~size()-1之间)

对象包装器与自动装箱

参数数量可变的方法

枚举类

反射

Class类

捕获异常

利用反射分析类的能力

package reflection;

import java.util.*;
import java.lang.reflect.*;

/**
 * This program uses reflection to print all features of a class.
 * @version 1.1 2004-02-21
 * @author Cay Horstmann
 */
public class ReflectionTest
{
   public static void main(String[] args)
   {
      // read class name from command line args or user input
      String name;
      if (args.length > 0) name = args[0];
      else
      {
         Scanner in = new Scanner(System.in);
         System.out.println("Enter class name (e.g. java.util.Date): ");
         name = in.next();
      }

      try
      {
         // print class name and superclass name (if != Object)
         Class cl = Class.forName(name);
         Class supercl = cl.getSuperclass();
         String modifiers = Modifier.toString(cl.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");
         System.out.print("class " + name);
         if (supercl != null && supercl != Object.class) System.out.print(" extends "
               + supercl.getName());

         System.out.print("\n{\n");
         printConstructors(cl);
         System.out.println();
         printMethods(cl);
         System.out.println();
         printFields(cl);
         System.out.println("}");
      }
      catch (ClassNotFoundException e)
      {
         e.printStackTrace();
      }
      System.exit(0);
   }

   /**
    * Prints all constructors of a class
    * @param cl a class
    */
   public static void printConstructors(Class cl)
   {
      Constructor[] constructors = cl.getDeclaredConstructors();

      for (Constructor c : constructors)
      {
         String name = c.getName();
         System.out.print("   ");
         String modifiers = Modifier.toString(c.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.print(name + "(");

         // print parameter types
         Class[] paramTypes = c.getParameterTypes();
         for (int j = 0; j < paramTypes.length; j++)
         {
            if (j > 0) System.out.print(", ");
            System.out.print(paramTypes[j].getName());
         }
         System.out.println(");");
      }
   }

   /**
    * Prints all methods of a class
    * @param cl a class
    */
   public static void printMethods(Class cl)
   {
      Method[] methods = cl.getDeclaredMethods();

      for (Method m : methods)
      {
         Class retType = m.getReturnType();
         String name = m.getName();

         System.out.print("   ");
         // print modifiers, return type and method name
         String modifiers = Modifier.toString(m.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.print(retType.getName() + " " + name + "(");

         // print parameter types
         Class[] paramTypes = m.getParameterTypes();
         for (int j = 0; j < paramTypes.length; j++)
         {
            if (j > 0) System.out.print(", ");
            System.out.print(paramTypes[j].getName());
         }
         System.out.println(");");
      }
   }

   /**
    * Prints all fields of a class
    * @param cl a class
    */
   public static void printFields(Class cl)
   {
      Field[] fields = cl.getDeclaredFields();

      for (Field f : fields)
      {
         Class type = f.getType();
         String name = f.getName();
         System.out.print("   ");
         String modifiers = Modifier.toString(f.getModifiers());
         if (modifiers.length() > 0) System.out.print(modifiers + " ");         
         System.out.println(type.getName() + " " + name + ";");
      }
   }
}

在运行时使用反射分析对象

```java
// ObjectAnalyzer.java
package objectAnalyzer;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
public class ObjectAnalyzer
{
private ArrayList<Object> visited = new ArrayList<>();

/**
    * Converts an object to a string representation that lists all fields.
    * @param obj an object
    * @return a string with the object's class name and all field names and
    * values
    */
public String toString(Object obj)
{
    if (obj == null) return "null";
    if (visited.contains(obj)) return "...";
    visited.add(obj);
    Class cl = obj.getClass();
    if (cl == String.class) return (String) obj;
    if (cl.isArray())
    {
        String r = cl.getComponentType() + "[]{";
        for (int i = 0; i < Array.getLength(obj); i++)
        {
            if (i > 0) r += ",";
            Object val = Array.get(obj, i);
            if (cl.getComponentType().isPrimitive()) r += val;
            else r += toString(val);
        }
        return r + "}";
    }

    String r = cl.getName();
    // inspect the fields of this class and all superclasses
    do
    {
        r += "[";
        Field[] fields = cl.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
        // get the names and values of all fields
        for (Field f : fields)
        {
            if (!Modifier.isStatic(f.getModifiers()))
            {
            if (!r.endsWith("[")) r += ",";
            r += f.getName() + "=";
            try
            {
                Class t = f.getType();
                Object val = f.get(obj);
                if (t.isPrimitive()) r += val;
                else r += toString(val);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            }
        }
        r += "]";
        cl = cl.getSuperclass();
    }
    while (cl != null);

    return r;
}
}
// ObjectAnalyzerTest.java
package objectAnalyzer;
import java.util.ArrayList;
/**
* This program uses reflection to spy on objects.
* @version 1.12 2012-01-26
* @author Cay Horstmann
*/
public class ObjectAnalyzerTest
{
public static void main(String[] args)
{
    ArrayList<Integer> squares = new ArrayList<>();
    for (int i = 1; i <= 5; i++)
        squares.add(i * i);
    System.out.println(new ObjectAnalyzer().toString(squares));
}
}
```

使用反射编写泛型数组代码

调用任意方法

继承的设计技巧

  1. 将公共操作和域放在超类

    这就是为什么将姓名域放在Person类中,而没有将它放在Employee和Student类中的原因。

  2. 不要使用受保护的域

    然而,protected机制并不能够带来更好的保护,其原因主要有两点。第一,子类集合是无限制的,任何一个人都能够由某个类派生一个子类,并编写代码以直接访问protected的实例域,从而破坏了封装性。第二,在Java程序设计语言中,在同一个包中的所有类都可以访问proteced域,而不管它是否为这个类的子类。

  3. 使用继承实现“is-a”关系

  1. 除非所有继承的方法都有意义,否则不要使用继承

  2. 在覆盖方法时,不要改变预期的行为

  3. 使用多态,而非类型信息

    使用多态方法或接口编写的代码比使用对多种类型进行检测的代码更加易于维护和扩展。像下面这种代码完全可以用继承与多态来解决

    if (x is of type 1) action1(x);
    else if (x is of type 2) action2(x);
    
  4. 不要过多地使用反射

反射机制使得人们可以通过在运行时查看域和方法,让人们编写出更具有通用性的程序。这种功能对于编写系统程序来说极其实用,但是通常不适于编写应用程序。反射是很脆弱的,即编译器很难帮助人们发现程序中的错误,因此只有在运行时才发现错误并导致异常。

上一篇 下一篇

猜你喜欢

热点阅读