java小知识点总结


------------- java培训android培训、java博客、java学习型技术博客、期待与您交流! --------------

 




假克隆:

      对于基本类型可以使用 = 来进行克隆,此时两个变量除了相等没有任何关系,

      但对于引用类型却不能简单的使用 = 进行克隆,这主要是于 java的内存空间使用有关。

       通常情况很少使用 = 来操作对象,也很少使用 == 来比较两个对象。


      定义一个Employee类: 如下
  1. package com.mingrisoft.oop;

  2. public class Employee {
  3.     private String name;
  4.     private int age;
  5.     
  6.     public String getName() {
  7.         return name;
  8.     }
  9.     
  10.     public void setName(String name) {
  11.         this.name = name;
  12.     }
  13.     
  14.     public int getAge() {
  15.         return age;
  16.     }
  17.     
  18.     public void setAge(int age) {
  19.         this.age = age;
  20.     }
  21.     
  22.     @Override
  23.     public String toString() {
  24.         return "姓名:" + name + ", 年龄:" + age;
  25.     }
  26. }
复制代码
以下是main函数:
  1. package com.mingrisoft.oop;

  2. public class Test {
  3.     public static void main(String[] args) {
  4.         System.out.println("克隆之前:");
  5.         Employee employee1 = new Employee();
  6.         employee1.setName("java1");
  7.         employee1.setAge(12);
  8.         System.out.println("员工1的信息:");
  9.         System.out.println(employee1);
  10.         
  11.         
  12.         
  13.         System.out.println("克隆之后:");
  14.         Employee employee2 = employee1;
  15.         employee2.setName("web1");
  16.         employee2.setAge(34);
  17.         System.out.println("员工2的信息:");
  18.         System.out.println(employee2);
  19.         
  20.         System.out.println("员工1的信息:");
  21.         System.out.println(employee1);
  22.     }
  23. }
复制代码
打印信息如下:
  1. 克隆之前:
  2. 员工1的信息:
  3. 姓名:java1, 年龄:12
  4. 克隆之后:
  5. 员工2的信息:
  6. 姓名:web1, 年龄:34
  7. 员工1的信息:
  8. 姓名:web1, 年龄:34
复制代码
当修改Employee2 的时候  employmee1 的内容也被修改了。并没有达到克隆目的。




浅克隆如下:
  1. package com.mingrisoft.oop;

  2. <font color="#ff0000">public class Employee implements Cloneable {</font>
  3.     private String name;
  4.     private int age;
  5.     private Address address; <font color="#ff0000">  //此变量是一个自定义里变量。</font>
  6.     
  7.     public Employee(String name, int age, Address address) {
  8.         this.name = name;
  9.         this.age = age;
  10.         this.address = address;
  11.     }
  12.     
  13.     public String getName() {
  14.         return name;
  15.     }
  16.     
  17.     public void setName(String name) {
  18.         this.name = name;
  19.     }
  20.     
  21.     public int getAge() {
  22.         return age;
  23.     }
  24.     
  25.     public void setAge(int age) {
  26.         this.age = age;
  27.     }
  28.     
  29.     public Address getAddress() {
  30.         return address;
  31.     }
  32.     
  33.     public void setAddress(Address address) {
  34.         this.address = address;
  35.     }
  36.     
  37.     @Override
  38.     public String toString() {
  39.         StringBuilder sb = new StringBuilder();
  40.         sb.append("姓名:" + name + ", ");
  41.         sb.append("年龄:" + age + "\n");
  42.         sb.append("地址:" + address);
  43.         return sb.toString();
  44.     }
  45.     
  46. <font color="#ff0000">    @Override
  47.     public Employee clone() {
  48.         Employee employee = null;
  49.         try {
  50.             employee = (Employee) super.clone();
  51.         } catch (CloneNotSupportedException e) {
  52.             e.printStackTrace();
  53.         }
  54.         return employee;
  55.     }</font>
  56. }
复制代码
main函数如下:
  1. package com.mingrisoft.oop;

  2. public class Test {
  3.     public static void main(String[] args) {
  4.         System.out.println("克隆之前:");
  5.         Address address = new Address("河北", "邯郸", "丛台");
  6.         Employee employee1 = new Employee("占二", 12, address);
  7.         System.out.println("员工1的信息:");
  8.         System.out.println(employee1);
  9.         
  10.         
  11.         System.out.println("克隆之后:");
  12.         Employee employee2 = employee1.clone();
  13.         employee2.getAddress().setState("中国");
  14.         employee2.getAddress().setProvince("云南");
  15.         employee2.getAddress().setCity("昆明");
  16.         employee2.setName("国美");
  17.         employee2.setAge(114);
  18.         
  19.         System.out.println("员工2的信息:");
  20.         System.out.println(employee2);
  21.         System.out.println("员工1的信息:");
  22.         System.out.println(employee1);
  23.     }
  24. }
复制代码
打印信息如下:
  1. 克隆之前:
  2. 员工1的信息:
  3. 姓名:占二, 年龄:12
  4. 地址:国家:河北, 省:邯郸, 市:丛台
  5. 克隆之后:
  6. 员工2的信息:
  7. 姓名:国美, 年龄:114
  8. 地址:国家:中国, 省:云南, 市:昆明
  9. 员工1的信息:
  10. 姓名:占二, 年龄:12
  11. 地址:国家:中国, 省:云南, 市:昆明
复制代码
分析可见 : 占二的姓名和年龄不没有被修改,但是地址信息被更改了。 因为 String  int  都可以实现值拷贝

                      有于自定义Address 类没有实现  Cloneable   接口所以,不能实现克隆,而是指向了同一个对象。






深克隆如下:
  1. package com.mingrisoft.oop;

  2. <font color="#ff0000">public class Address implements Cloneable {</font>
  3.     private String state;
  4.     private String province;
  5.     private String city;
  6.     
  7.     public Address(String state, String province, String city) {
  8.         this.state = state;
  9.         this.province = province;
  10.         this.city = city;
  11.     }
  12.     
  13.     public String getState() {
  14.         return state;
  15.     }
  16.     
  17.     public void setState(String state) {
  18.         this.state = state;
  19.     }
  20.     
  21.     public String getProvince() {
  22.         return province;
  23.     }
  24.     
  25.     public void setProvince(String province) {
  26.         this.province = province;
  27.     }
  28.     
  29.     public String getCity() {
  30.         return city;
  31.     }
  32.     
  33.     public void setCity(String city) {
  34.         this.city = city;
  35.     }
  36.     
  37.     @Override
  38.     public String toString() {
  39.         StringBuilder sb = new StringBuilder();
  40.         sb.append("国家:" + state + ", ");
  41.         sb.append("省:" + province + ", ");
  42.         sb.append("市:" + city);
  43.         return sb.toString();
  44.     }
  45.     
  46. <font color="#ff0000">    @Override
  47.     protected Address clone() {
  48.         Address address = null;
  49.         try {
  50.             address = (Address) super.clone();
  51.         } catch (CloneNotSupportedException e) {
  52.             e.printStackTrace();
  53.         }
  54.         return address;
  55.     }</font>
  56. }
复制代码
  1. package com.mingrisoft.oop;

  2. <font color="#ff0000">public class Employee implements Cloneable {</font>
  3.     private String name;
  4.     private int age;
  5.     private Address address;
  6.     
  7.     public Employee(String name, int age, Address address) {
  8.         this.name = name;
  9.         this.age = age;
  10.         this.address = address;
  11.     }
  12.     
  13.     public String getName() {
  14.         return name;
  15.     }
  16.     
  17.     public void setName(String name) {
  18.         this.name = name;
  19.     }
  20.     
  21.     public int getAge() {
  22.         return age;
  23.     }
  24.     
  25.     public void setAge(int age) {
  26.         this.age = age;
  27.     }
  28.     
  29.     public Address getAddress() {
  30.         return address;
  31.     }
  32.     
  33.     public void setAddress(Address address) {
  34.         this.address = address;
  35.     }
  36.     
  37.     @Override
  38.     public String toString() {
  39.         StringBuilder sb = new StringBuilder();
  40.         sb.append("姓名:" + name + ", ");
  41.         sb.append("年龄:" + age + "\n");
  42.         sb.append("地址:" + address);
  43.         return sb.toString();
  44.     }
  45.     
  46. <font color="#ff0000">    @Override
  47.     public Employee clone() {
  48.         Employee employee = null;
  49.         try {
  50.             employee = (Employee) super.clone();</font>
  51. <font color="#9acd32">            employee.address = address.clone();</font>
  52. <font color="#ff0000">        } catch (CloneNotSupportedException e) {
  53.             e.printStackTrace();
  54.         }
  55.         return employee;
  56.     }</font>
  57. }
复制代码
打印信息如下:
克隆之前:
员工1的信息:
姓名:占二, 年龄:12
地址:国家:河北, 省:邯郸, 市:丛台

克隆之后:

员工2的信息:
姓名:国美, 年龄:114
地址:国家:中国, 省:云南, 市:昆明

员工1的信息:
姓名:占二, 年龄:12
地址:国家:河北, 省:邯郸, 市:丛台



占二的信息并没有被更改,从而实现了深克隆。









1: 关于控制符的使用:

        *    类的绝大部分Field 都应该使用private修饰,只有一些static 修饰的,类似全局变量的Field才考虑
              使用public 修饰,所以不要动不动就整 public,此外,有些方法只是用于辅助该类的其他方法,这些方法
               被称为工具方法,工具方法也应该用private 修饰。

       *     如果某个类主要用作其他类的父类,该类里包含的大部分方法可能仅希望被其子类重写,而不想被外界
              直接调用,则应该使用protected 来修饰。

       *    希望暴露出来给其他类自由调用的方法应该使用public来修饰,因此类的构造器通过使用public 修饰,从而允许在其他
             的地方创建该类的实例。

2:     java 的常用包:

       *  java.lang   这个包下包含了java的核心类,如String  Math  System  和 Thread 类等,使用这个包无需使用import 语句导入,
                            系统会自动导入
       *  java.util    这个包下包含java的大量的工具类、接口和集合框架类、接口,例如Arrays  List  Set 

      *  java.net    这个包是java网络编程相关的类和接口。

       *  java.io    这个包是输入和输出相关的类和接口。

       * java.text   这个包包含了了一些java 格式化相关的类。

       * java.sql   这个包包含了java 进行JDBC 数据库编程的相关类和接口。

       * java.awt   抽象窗口工具集,主要用于构建GUI界面。

       * java.swing  包含了Swing 图形用户界面编程的相关类和接口。这些类是轻量级的,用于构建和平台无关的GUI程序。




3:  子类 和父类 :

          如果在子类中定义了与父类已有变量同名的变量,那么子类中定义的变量会 隐藏 父类中定义的变量。注意不是完全覆盖,

          因此系统在创建子类对象时,依然会为父类中定义的、被隐藏的变量分配内存空间。

          所以: 为了在子类中能够访问到父类中定义的、被隐藏的实例变量。或者为了在子类中访问父类中定义的、被隐藏的方法,
                      可用通过super.  在达到访问的目的。


4:   子类构造器调用父类构造器的集中情况:

          *   子类构造器执行体的第一行使用super 显示调用父类的构造器,系统将根据super 传入的实参列表调用父类对应的构造器。

          *   子类构造器执行体的第一行使用this 显示调用本类中的重载构造器,系统根据this 调用里传入的实参调用本类中的另一个构造
               器,而在这个构造器中会调用父类的构造器。

          *   子类构造器执行体中既没有super 调用,也没有this 调用,系统将会在执行子类构造器之前,隐士调用父类无参的构造器。

5: instanceof

            instanceof  和  (type )  是java 提供的两个相关的运算符,通常先用instanceof 判断一个对象是否可以强制类型转换,

            然后才使用(type) 进行强制类型转换,从而保证程序不会出现错误。

6: 设计父类应该遵守如下规则:

        *   尽量隐藏父类的内部数据,不要让子类直接访问父类的field 

        *   不要让子类可以随意访问修改 父类的方法。

        *   尽量不要在父类构造器中调用将要被子类重写的方法。 否则可能引起空指针异常。

7:   抽象类和抽象方法:

          * 抽象类必须使用abstract 来修饰,抽象方法也必须使用abstract来修饰,抽象方法不能有方法体。

         *  抽象类不能被实例化。

         *  抽象类可以包含 Field  方法  构造器  初始化块  内部类   枚举类  6部分,抽象类的构造器不能用于创建实例,主要用于被其子类调用。

         *  含有抽象方法的类只能被定义为 抽象类。 

8:  abstract 关键字使用注意点:

        * final 修饰的类不能被继承,final 修饰的方法不能被重写,所以 final  和abstract 永远不能被同时使用。

         * 当使用static 修饰一个方法时,表明这个方法属于这个类本身,如果将该方法定义为抽象方法,则将导致通过该类
            调用该方法是出现错误(调用一个没有方法体的方法肯定会出错) 
            因此 static  和abstract  不能同时修饰某一个方法,即没有所谓的类抽象方法。

9:   接口注意:

         *  对于接口定义的方法,他们只能是抽象方法,因此系统会自动为其增加abstract 修饰符,
             由于接口里的方法全部是抽象方法,因此接口里不允许定义静态方法,即不可以使用
             static 修饰接口里定义的方法。

         * 不管接口里方法是否用public abstract 来修饰,默认都采用public abstract 来修饰。




死锁与死锁解决

以下是一个会产生死锁的例子:
  1. package com.mingrisoft.thread;

  2. public class DeadLock implements Runnable {
  3.     private boolean flag;// 使用flag变量作为进入不同块的标志
  4.     private static final Object o1 = new Object();
  5.     private static final Object o2 = new Object();
  6.     
  7.     public void run() {
  8.         String threadName = Thread.currentThread().getName();// 获得当前线程的名字
  9.         System.out.println(threadName + ": flag = " + flag);// 输出当前线程的flag变量值
  10.         if (flag == true) {
  11.             synchronized (o1) {// 为o1加锁
  12.                 try {
  13.                     Thread.sleep(1000);// 线程休眠1秒钟
  14.                 } catch (InterruptedException e) {
  15.                     e.printStackTrace();
  16.                 }
  17.                 System.out.println(threadName + "进入同步块o1准备进入o2");// 显示进入o1块
  18.                 synchronized (o2) {// 为o2加锁
  19.                     System.out.println(threadName + "已经进入同步块o2");// 显示进入o2块
  20.                 }
  21.             }
  22.         }
  23.         if (flag == false) {
  24.             synchronized (o2) {
  25.                 try {
  26.                     Thread.sleep(1000);
  27.                 } catch (InterruptedException e) {
  28.                     e.printStackTrace();
  29.                 }
  30.                 System.out.println(threadName + "进入同步块o2准备进入o1");// 显示进入o2块
  31.                 synchronized (o1) {
  32.                     System.out.println(threadName + "已经进入同步块o1");// 显示进入o1块
  33.                 }
  34.             }
  35.         }
  36.     }
  37.     
  38.     public static void main(String[] args) {
  39.         DeadLock d1 = new DeadLock();// 创建DeadLock对象d1
  40.         DeadLock d2 = new DeadLock();// 创建DeadLock对象d2
  41.         d1.flag = true; // 将d1的flag设置为true
  42.         d2.flag = false; // 将d2的flag设置为false
  43.         new Thread(d1).start();// 在新线程中运行d1的run()方法
  44.         new Thread(d2).start();// 在新线程中运行d2的run()方法
  45.     }
  46. }
复制代码
Thread(d1)和  Thread(d2)启动后会分别进入不同的if 分支
此时Thread(d1) 占有锁01    Thread(d2) 占有锁o2
sleep后 Thread(d1) 会去请求资源o2   而 Thread(d2)会去请求资源o1
这样你不给我不让  就造成了死锁。


死锁的条件如下:
  1:    资源互斥(资源只能供一个线程使用)
  2:  请求保持(拥有资源的线程在请求新的资源又不释放占有的资源)
  3:  不能掠夺(已经获得的资源在使用完成前不能掠夺)
  4:  循环等待(各个线程对资源的需求构成一个循环)




以上例子的解决办法:
  1. public void run() {
  2.         String threadName = Thread.currentThread().getName();// 获得当前线程的名字
  3.         System.out.println(threadName + ": flag = " + flag);// 输出当前线程的flag变量值
  4.         if (flag == true) {
  5.             synchronized (o1) {// 为o1加锁
  6.                 try {
  7.                     Thread.sleep(1000);// 线程休眠1秒钟
  8.                 } catch (InterruptedException e) {
  9.                     e.printStackTrace();
  10.                 }
  11.                 System.out.println(threadName + "进入同步块o1准备进入o2");// 显示进入o1块
  12.                 System.out.println(threadName + "已经进入同步块o2");// 显示进入o2块<font color="#ff0000"><b>***********注意少了synchronized (o2) </b></font>
  13.             }
  14.             if (flag == false) {
  15.                 synchronized (o2) {
  16.                     try {
  17.                         Thread.sleep(1000);
  18.                     } catch (InterruptedException e) {
  19.                         e.printStackTrace();
  20.                     }
  21.                     System.out.println(threadName + "进入同步块o2准备进入o1");// 显示进入o2块
  22.                     synchronized (o1) {
  23.                         System.out.println(threadName + "已经进入同步块o1");// 显示进入o1块
  24.                     }
  25.                 }
  26.             }
  27.         }
复制代码
解决办法 : 对于这四个同步块,去掉任何一个就可以解决死锁的问题。



死锁的输出如下:Thread-0: flag = true
Thread-1: flag = false
Thread-1进入同步块o2准备进入o1
Thread-0进入同步块o1准备进入o2





常见的异常类型

1:   算数异常   ArithmeticException           
         除0 导致的异常
  1. package com.mingrisoft.exceptions;

  2. public class ExceptionTest {
  3.     public static void main(String[] args) {
  4.         System.out.println("-1.0 / 0 = " + (-1.0 / 0));// 演示负浮点数除0
  5.         System.out.println("+1.0 / 0 = " + (+1.0 / 0));// 演示正浮点数除0
  6.         System.out.println("-1 / 0 = " + (-1 / 0));// 演示负整数除0
  7.         System.out.println("+1 / 0 = " + (-1 / 0));// 演示正整数除0
  8.     }
  9. }
复制代码
错误:Exception in thread "main" java.lang.ArithmeticException: / by zero

2:  数组存值异常  ArrayStoreException

              在String 数组中存入了 Integer 对象
  1. package com.mingrisoft.exceptions;

  2. public class ExceptionTest {
  3.     public static void main(String[] args) {
  4.         Object array[] = new String[3]; // 声明一个长度为3的Object类型的数组
  5.         array[0] = new Integer(1); // 将数组的第一个元素赋值为整数对象1
  6.         System.out.println(array[0]); // 输出数组的第一个元素
  7.     }
  8. }
复制代码
错误: Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer



3:  数组下标越界异常  ArrayIndexOutOfBoundsException


             数组length为 5, 遍历的时候到了 5
  1. package com.mingrisoft.exceptions;

  2. import java.util.Arrays;

  3. public class ExceptionTest {
  4.     public static void main(String[] args) {
  5.         int[] array = new int[5]; // 声明一个长度为5的整型数组
  6.         Arrays.fill(array, 8); // 将新声明的数组所有元素赋值为8
  7.         for (int i = 0; i < 6; i++) {// 遍历输出所有数组元素
  8.             System.out.println("array[" + i + "] = " + array[i]);
  9.         }
  10.     }
  11. }
复制代码
错误: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5

4:  空指针异常  NullPointerException
             string 对象为 null  
             调用 它的函数会导致空指针异常。
  1. package com.mingrisoft.exceptions;

  2. public class ExceptionTest {
  3.     @SuppressWarnings("null")
  4.     public static void main(String[] args) {
  5.         String string = null;// 将字符串设置为null
  6.         System.out.println(string.toLowerCase());// 将字符串转换成小写
  7.     }
  8. }
复制代码
错误: Exception in thread "main" java.lang.NullPointerException

5: 类未发现异常  ClassNotFoundException

              由于我本机并没有 com.mysql.jdbc.Driver
  1. package com.mingrisoft.exceptions;

  2. public class ExceptionTest {
  3.     public static void main(String[] args) {
  4.         try {
  5.             Class.forName("com.mysql.jdbc.Driver");// 加载MySQL驱动程序
  6.         } catch (ClassNotFoundException e) {// 捕获异常
  7.             e.printStackTrace();// 打印堆栈信息
  8.         }
  9.     }
  10. }
复制代码
错误: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

6:   非法访问异常     IllegalAccessException
         这个例子是涉及到反射技术。


          试图要访问String  这个类 中的hash 成员变量。 hash 变量为private
  1. package com.mingrisoft.exceptions;

  2. import java.lang.reflect.Field;

  3. public class ExceptionTest {
  4.     public static void main(String[] args) {
  5.         Class<?> clazz = String.class;// 获得代表String类的类对象
  6.         Field[] fields = clazz.getDeclaredFields();// 获得String类的所有域
  7.         for (Field field : fields) {// 遍历所有域
  8.             if (field.getName().equals("hash")) {// 如果域的名字是hash
  9.                 try {
  10.                     System.out.println(field.getInt("hash"));// 输出hash的值
  11.                 } catch (IllegalArgumentException e) {
  12.                     e.printStackTrace();
  13.                 } catch (IllegalAccessException e) {
  14.                     e.printStackTrace();
  15.                 }
  16.             }
  17.         }
  18.     }
  19. }
复制代码
错误: java.lang.IllegalAccessException: Class com.mingrisoft.exceptions.ExceptionTest can not access a member of class java.lang.String with modifiers "private"


7: 文件未发现异常:  FileNotFoundException

             我的机子并没有这个文件 d:\\kira.txt"  
  1. package com.mingrisoft.exceptions;

  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;

  6. public class ExceptionTest {
  7.     public static void main(String[] args) {
  8.         FileInputStream fis = null;// 创建一个文件输入流对象
  9.         try {
  10.             File file = new File("d:\\kira.txt");// 创建一个文件对象
  11.             fis = new FileInputStream(file);// 初始化文件输入流对象
  12.         } catch (FileNotFoundException e) {// 捕获异常
  13.             e.printStackTrace();
  14.         } finally {
  15.             try {
  16.                 fis.close();// 释放资源
  17.             } catch (IOException e) {
  18.                 e.printStackTrace();
  19.             }
  20.         }
  21.     }
  22. }
复制代码
错误: java.io.FileNotFoundException: d:\kira.txt (系统找不到指定的文件。)





------------- java培训android培训、java博客、java学习型技术博客、期待与您交流! -------------

详情请查看:http://edu.csdn.net/heima/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值