Java進階知識

批處理文件(bat)

簡單的說,批處理的做用就是自動的連續執行多條命令 .編寫bat處理文件可使用記事本的方式:java

常見批處理文件的命令:spring

echo 表示顯示此命令後的字符 編程

tiltle 設置窗口的標題。設計模式

echo off 表示在此語句後全部運行的命令都不顯示命令行自己 數組

color 設置窗體的字體顏色。緩存

@echo off相象,但它是加在每一個命令行的最前面,表示運行時不顯示這一行的命令行(只能影響當前行)。 安全

pause 運行此句會暫停批處理的執行並在屏幕上顯示Press any key to continue...的提示,等待用戶按任意鍵後繼續 框架

rem 表示此命令後的字符爲解釋行(註釋),不執行,只是給本身從此參考用的(至關於程序中的註釋) 或者%註釋的內容%dom

%[1-9]表示參數,參數是指在運行批處理文件時在文件名後加的以空格(或者Tab)分隔的字符串ide

對象拷貝

2.1 對象的淺拷貝

淺複製(淺克隆)被複制對象的全部變量都含有與原來對象相同的值,而全部的對其餘對象的引用仍然只指向原來的對象,換言之,淺複製僅僅複製鎖考慮的對象,而不復制它所引用的對象。

 

public class Student implements Cloneable{

 String name;

 int age;

 Student(String name,int age){

  this.name=name;

  this.age=age;

 }

 

 public Object clone(){

  Object o =null;

  try{

   o=super.clone();//Object中的clone()識別出你要複製的哪個對象

  }

  catch(CloneNotSupportedException e){

   System.out.println(e.toString());

  }

  return o;

 }

 

 public static void main(String[] args){

  Student s1 = new Student("zhang",18);

  Student s2 = (Student)s1.clone();

  s2.name="li";

  s2.age=20;

  System.out.println("name="+s1.name+","+"age="+s1.age);//修改學生2後不影響學生1的值

   }

}

 

 

2.2 對象深拷貝

深複製(深克隆)被複制對象的全部變量都含有與原來的對象相同的值,除去那些引用其餘對象的變量,那些引用其餘對象的變量將指向被複制過的新對象,而再也不試原有的那些被引用的對象,換言之,深複製把要複製的對象所引用的對象都複製了一遍。

把對象寫到流裏的過程是串行化(Serilization)過程,可是在Java程序師圈子裏又很是形象地稱爲冷凍或者醃鹹菜(picking過程;而把對象從流中讀出來的並行化(Deserialization)過程則叫作解凍或者回鮮(depicking)」過程。應當指出的是,寫在流裏的是對象的一個拷貝,而原對象仍然存在於JVM裏面,所以醃成鹹菜的只是對象的一個拷貝,Java鹹菜還能夠回鮮。

Java語言裏深複製一個對象,經常能夠先使對象實現Serializable接口,而後把對象(實際上只是對象的一個拷貝)寫到一個流裏(醃成鹹菜),再從流裏讀出來(把鹹菜回鮮),即可以重建對象。

public Object deepClone()

{

 //將對象寫到流裏

 ByteArrayOutoutStream bo=new ByteArrayOutputStream();

 ObjectOutputStream oo=new ObjectOutputStream(bo);

 oo.writeObject(this);

 //從流裏讀出來

 ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());

 ObjectInputStream oi=new ObjectInputStream(bi);

 return(oi.readObject());

}

 

1. 內存溢出

因爲Java具有自動的垃圾回收機制,當咱們使用完對象以後,它們會被自動回收,是否是咱們在Java程序中不須要再考慮內存管理了嗎?

請看以下程序:

class Stack {

private Object[] elements;

// 初始化角標

int index = 0;

// 默認初始化容量

private int initialCapacity = 10;

 

public Stack() {

elements = new Object[initialCapacity];

}

 

// 壓棧 push

public void push(Object e) {

ensureCapacity();

elements[index++] = e;

// System.out.println(index);

}

 

// 彈棧 pop

public Object pop() {

if (index == 0) {

throw new RuntimeException("沒有元素");

}

return elements[--index];

}

 

private void ensureCapacity() {

if (index == elements.length) {

elements = Arrays.copyOf(elements, index * 2 + 1);

}

}

}

 

注意:從棧中彈出的對象不會做爲垃圾回收,即便程序再也不使用這些對象,由於棧內部繼續維護着這些對象.最終可能會致使內存佔用的不斷增長,程序性能下降.這就是內存泄漏.

改進版本

class Stack {

private Object[] elements;

// 初始化角標

int index = 0;

// 默認初始化容量

private int initialCapacity = 10;

 

public Stack() {

elements = new Object[initialCapacity];

}

 

// 壓棧 push

public void push(Object e) {

ensureCapacity();

elements[index++] = e;

// System.out.println(index);

}

 

// 彈棧 pop

public Object pop() {

if (index == 0) {

throw new RuntimeException("沒有元素");

}

Object obj = elements[--index];

elements[index] = null;

return obj;

}

 

private void ensureCapacity() {

if (index == elements.length) {

elements = Arrays.copyOf(elements, index * 2 + 1);

}

}

}

 

2. 設計模式

設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。

2.1. 觀察者模式

有時又被稱爲

發佈-訂閱<Publish/Subscribe>模式、

模型-視圖<Model/View>模式、

-收聽者<Source/Listener>模式

或從屬者<Dependents>模式)

這是軟件設計模式的一種。

觀察者模式(Observer)完美的將觀察者和被觀察的對象分離開。

此種模式中,一個目標物件管理全部相依於它的觀察者物件,而且在它自己的狀態改變時主動發出通知。

這一般透過呼叫各觀察者所提供的方法來實現。

此種模式一般被用來實做事件處理系統。

有多個觀察者時,不能夠依賴特定的通知次序。

Swing大量使用觀察者模式,許多GUI框架也是如此。

氣象站:

public class WeatherStation {

 

private String weather;

 

String[] weathers = {"下雨","下雪","下冰雹","出太陽"};

 

static List<BookWeather> list = new ArrayList<BookWeather>();

 

Random random = new Random();

 

 

public void startWork(){

 

new Thread(){

 

@Override

public void run() {

while(true){

updateWeather();

try {

Thread.sleep(random.nextInt(1000)+500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

}

public void updateWeather(){

weather = weathers[random.nextInt(4)];

System.out.println("天氣:"+ weather);

}

 

 

public String getWeather() {

return weather;

}

人:

public class Person implements BookWeather {

 

String name;

 

public  Person(String name){

this.name = name;

}

 

private WeatherStation station ;

 

public Person(String name,WeatherStation station){

this(name);

this.station = station;

}

 

//下雨","下雪 ","下冰雹","出太陽"

@Override

public void notifyWeather() {

String weather = station.getWeather();

if("下雨".equals(weather)){

System.out.println(name+"打着雨傘上班");

}else if("下雪".equals(weather)){

System.out.println(name+"溜冰 上班");

}else if("下冰雹".equals(weather)){

System.out.println(name+"帶着頭盔 上班");

}else if("出太陽".equals(weather)){

System.out.println(name+"嗮着太陽 上班");

}

}

 

}

 

測試類:

 

public class Test {

 

public static void main(String[] args) throws InterruptedException {

WeatherStation station = new WeatherStation();

station.startWork();

 

Person p1 = new Person("小明",station);

while(true){

p1.notifyWeather();

Thread.sleep(2000);

}

}

問題:天氣變化兩三次,小明才知道一次。

解決方案

package cn.itcast.test;

import java.util.List;

import java.util.ArrayList;

import java.util.Random;

public class WeatherStation {

 

private String weather;

 

String[] weathers = {"下雨","下雪","下冰雹","出太陽"};

 

private static List<BookWeather> list = new ArrayList<BookWeather>();

 

Random random = new Random();

 

public void addListaner(BookWeather e){

list.add(e);

}

 

public void startWork(){

 

new Thread(){

 

@Override

public void run() {

while(true){

updateWeather();

try {

Thread.sleep(random.nextInt(1000)+500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}.start();

}

public void updateWeather(){

weather = weathers[random.nextInt(4)];

System.out.println("天氣:"+ weather);

for(BookWeather item : list){

item.notifyWeather(weather);

}

}

 

 

public String getWeather() {

return weather;

}

 

人:

public class Person implements BookWeather {

 

String name;

 

public  Person(String name){

this.name = name;

}

 

private WeatherStation station ;

 

public Person(String name,WeatherStation station){

this(name);

this.station = station;

}

 

//下雨","下雪 ","下冰雹","出太陽"

@Override

public void notifyWeather(String weather) {

if("下雨".equals(weather)){

System.out.println(name+"打着雨傘上班");

}else if("下雪".equals(weather)){

System.out.println(name+"溜冰 上班");

}else if("下冰雹".equals(weather)){

System.out.println(name+"帶着頭盔 上班");

}else if("出太陽".equals(weather)){

System.out.println(name+"嗮着太陽 上班");

}

}

 

}

接口:

 

public interface BookWeather {

 

public void notifyWeather(String weather);

}

 

 

public class Test {

 

public static void main(String[] args) throws InterruptedException {

WeatherStation station = new WeatherStation();

station.startWork();

 

Person p1 = new Person("小明");

Person p2 = new Person("小紅");

Person p3 = new Person("小青 ");

station.addListaner(p1);

station.addListaner(p2);

station.addListaner(p3);

 

}

}

 

 

2.2. 單例

Singleton

是指只能擁有一個實例的類就是單例類。

私有構造方法。

獲取方式

經過公共的靜態方法建立單一的實例。

兩種模式

懶漢模式一般被稱爲延遲加載。注意存在線程安全問題.

餓漢模式

懶漢式的單例模式線程安全問題的解決方案:

class Single{

 

//聲明本類的一個私有的成員變量

private static Single single;

 

//第一步 : 私有化構造方法

private Single(){

 

}

 //  第三步:提供一個公共的方法獲取該類的實例對象

public static Single getInstance(){

if(single==null){

synchronized (single) {

if(single==null){

 single = new Single();

}

}

}

return single;

}

}

3. 反射

類字節碼文件是在硬盤上存儲的,是一個個的.class文件。咱們在new一個對象時,JVM會先把字節碼文件的信息讀出來放到內存中,第二次用時,就不用在加載了,而是直接使用以前緩存的這個字節碼信息。

 

字節碼的信息包括:類名、聲明的方法、聲明的字段等信息。在Java萬物皆對象,這些信息固然也須要封裝一個對象,這就是Class類、Method類、Field類。

 

經過Class類、Method類、Field類等等類能夠獲得這個類型的一些信息,甚至能夠不用new關鍵字就建立一個實例,能夠執行一個對象中的方法,設置或獲取字段的值,這就是反射技術

3.1. Class

1.1.1. 獲取Class對象的三種方式

 

Java中有一個Class類用於表明某一個類的字節碼。

Java提供了三種方式獲取類的字節碼

forName()forName方法用於加載某個類的字節碼到內存中,並使用class對象進行封裝

類名.class

對象.getClass()

 

/**

 * 加載類的字節碼的3種方式

 * @throws Exception

 * */

public void test1() throws Exception {

// 方式一

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

// 方式二

Class clazz2 = Person.class;

// 方式三

Person p1 = new Person();

Class clazz3 = p1.getClass();

}

1.1.2. 經過Class類獲取類型的一些信息

1. getName()類的名稱(全名,全限定名)

2 getSimpleName()類的的簡單名稱(不帶包名)

3. getModifiers(); 類的的修飾符

4.建立對象

無參數構造建立對象

newInstance()

5. 獲取指定參數的構造器對象,並可使用Constructor對象建立一個實例

Constructor<T> getConstructor(Class<?>... parameterTypes)

 

/**

 * 經過Class對象獲取類的一些信息

 *

 * @throws Exception

 * */

private static void test2() throws Exception {

 

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

// 獲取類的名稱

String name = clazz1.getName();

System.out.println(name); // cn.itcast.gz.reflect.Person

// 獲取類的簡單名稱

System.out.println(clazz1.getSimpleName()); // Person

// 獲取類的修飾符

int modifiers = clazz1.getModifiers();

System.out.println(modifiers);

// 構建對象(默認調用無參數構造.)

Object ins = clazz1.newInstance();

Person p = (Person) ins;

System.out.println(p); // cn.itcast.gz.reflect.Person@c17164

// 獲取指定參數的構造函數

Constructor<?> con = clazz1.getConstructor(String.class, int.class);

// 使用Constructor建立對象.

Object p1 = con.newInstance("jack", 28);

System.out.println(((Person) p1).getName());

}

 

1.1.3. 經過Class類獲取類型中的方法的信息

1.獲取公共方法包括繼承父類的方法

getMethods()返回一個數組,元素類型是Method

2.獲取指定參數的公共方法

getMethod("setName", String.class);

3.得到全部的方法,包括私有

Method[] getDeclaredMethods()  

4.得到指定參數的方法,包括私有

Method getDeclaredMethod(String name, Class<?>... parameterTypes)

/**

 * 獲取公有方法.

 * @throws Exception

 * */

private static void test3() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

// 1.獲取非私用方法(包括父類繼承的方法)

Method[] methods = clazz1.getMethods();

System.out.println(methods.length);

for (Method m : methods) {

// System.out.println(m.getName());

if ("eat".equals(m.getName())) {

m.invoke(clazz1.newInstance(), null);

}

}

 

}

 

/**

 * 獲取指定方法簽名的方法

 *

 * @throws Exception

 * */

private static void test4() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

// 獲取指定名稱的函數

Method method1 = clazz1.getMethod("eat", null);

method1.invoke(new Person(), null);

}

 

/**

 * 獲取指定方法名且有參數的方法

 *

 * @throws Exception

 * */

private static void test5() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

Method method = clazz1.getMethod("eat", String.class);

method.invoke(new Person(), "包子");

}

 

/**

 * 獲取指定方法名,參數列表爲空的方法.

 *

 * @throws Exception

 * */

private static void test4() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

// 獲取指定名稱的函數

Method method1 = clazz1.getMethod("eat", null);

method1.invoke(new Person(), null);

}

 

/**

 * 反射靜態方法

 * @throws Exception

 * */

private static void test7() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

Method method = clazz1.getMethod("play", null);

method.invoke(null, null);

}

 

/**

 * 訪問私有方法 暴力反射

 * @throws Exception

 * */

private static void test6() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

Method method = clazz1.getDeclaredMethod("movie", String.class);

method.setAccessible(true);

method.invoke(new Person(), "蒼老師");

}

 

 

1.1.4. 經過Class類獲取類型中的字段的信息

1.獲取公共字段

Field[] getFields()  

2.獲取指定參數的公共字段

Field getField(String name)  

3.獲取全部的字段

Field[] getDeclaredFields()  

4.獲取指定參數的字段,包括私用

Field getDeclaredField(String name)  

 

/**

 * 獲取公有的字段

 * */

private static void test8() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

Field[] fields = clazz1.getFields();

Person p = new Person();

System.out.println(fields.length);

for (Field f : fields) {

System.out.println(f.getName());

if ("name".equals(f.getName())) {

System.out.println(f.getType().getName());

f.set(p, "jack");

}

}

System.out.println(p.getName());

 

}

 

 

/**

 * 獲取私有的字段

 * @throws Exception

 * */

private static void test9() throws Exception {

Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");

Field field = clazz1.getDeclaredField("age");

System.out.println(field.getName());

field.setAccessible(true);

Person p = new Person();

field.set(p, 100);

System.out.println(p.getAge());

}

 

 

3.2. 工廠模式

Factory

例如:汽車銷售商場

 

該模式將建立對象的過程放在了一個靜態方法中來實現.在實際編程中,若是須要大量的建立對象,該模式是比較理想的.

public class Demo1 {

public static void main(String[] args) {

System.out.println("買寶馬");

Car bmw = CarFactory("BMW");

bmw.run();

System.out.println("買大奔");

Car benz = CarFactory("Benz");

benz.run();

}

 

public static Car CarFactory(String carName) {

if ("BMW".equals(carName)) {

return new BMW();

} else if ("Benz".equals(carName)) {

return new Benz();

} else {

throw new RuntimeException("車型有誤");

}

}

}

 

abstract class Car {

 

public abstract void run();

}

 

class BMW extends Car {

 

@Override

public void run() {

System.out.println("BMW跑跑");

}

}

 

class Benz extends Car {

 

@Override

public void run() {

System.out.println("Benz跑跑");

}

}

 

模擬spring工廠:

import java.io.BufferedReader;

import java.io.FileReader;

import java.io.IOException;

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

class Student{

 

private int id;

 

private  String name;

 

public Student(int id , String name){

this.id = id;

this.name = name;

}

 

public Student(){

 

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

 

@Override

public String toString() {

return this.id +"-"+this.name;

}

 

}

class Person{

 

private int age;

 

public Person(){

 

}

 

 

 

 

@Override

public String toString() {

return this.age+"";

}

}

public class Demo1 {

 

public static void main(String[] args) throws Exception {

Object o = getInstance();

System.out.println(o);

 

}

 

public static Object getInstance() throws Exception{

FileReader fileReader = new FileReader("src/info.txt");

BufferedReader bufferedReader = new BufferedReader(fileReader);

String line = bufferedReader.readLine();

Class clazz  = Class.forName(line);

Constructor c =  clazz.getConstructor(null);

Object c1 = c.newInstance(null);

while((line=bufferedReader.readLine())!=null){

String[] datas =  line.split("=");

Field f = clazz.getDeclaredField(datas[0]);

f.setAccessible(true);

if(f.getType()==int.class){

f.set(c1, Integer.parseInt(datas[1]));

}else{

//f.setAccessible(true);

f.set(c1,datas[1]);

}

}

return c1;

}

 

 

 

}

相關文章
相關標籤/搜索