天天看點

java類加載 + android僞3d效果

一、java類的加載即其字段的初始化過程了解

聲明初始化永遠都是c系以及java等程式設計語言初學者避免不了的一個重要問題。了解這兩個概念,是接近語言本質的一小步,更是初學者的一大步。看了近一個月的thinking in java,我确實挺佩服Bruce Eckel出神入化的java神功,也為他行文的風格折服了不盡數次。而在這本神書的96頁,則對剛才所述的兩個概念在java中的表現形式有了一個很精辟的叙述。在此我就談談對這幾句的感受吧。

先對兩個概念給出本人自了解版的定義:

聲明:在記憶體中為某将要使用的語言要素(字段抑或方法)配置設定記憶體,并為其命名。如:int duck;就是在記憶體中配置設定了int所需的若幹位元組,然後給它取名為duck.這句就像你向别人說:哎,我要32塊錢去買隻鴨子。但鴨子是啥品種現在連你自己都還不知道。

初始化:為已聲明的記憶體第一次配置設定一個值。“已聲明”、“第一次”是這句話的關鍵。例如:int duck = 250;這句話就像你對别人說:哎,我要32塊錢去買隻鴨子,這隻鴨子是250。你現在很明确你要買什麼品種的鴨子,是以一聲明後,你就為它賦予了你想要給予它的特性。

有些書上老說,聲明初始化某變量,讓人看後以為聲明初始化是一個單獨的概念——額,其實是兩個啦。

好了,廢話少說,開講正文。

首先是那幾句原話:

(1) 類型為Dog的一個對象首次建立時,或者Dog類的static方法/static字段首次通路時,Java解釋器必須找到Dog.class(在事先設好的類路徑裡搜尋)。

(2) 找到Dog.class後(它會建立一個Class對象,這将在後面學到),它的所有static初始化子產品都會運作。是以,static初始化僅發生一次——在Class對象首次載入的時候。

(3) 建立一個new Dog()時,Dog對象的建構程序首先會在記憶體堆(Heap)裡為一個Dog對象配置設定足夠多的存儲空間。

(4) 這種存儲空間會清為零,将Dog中的所有基本類型設為它們的預設值(零用于數字,以及boolean和char的等價設定)。

(5) 進行字段定義時發生的所有初始化都會執行。

(6) 執行建構器。正如第6章将要講到的那樣,這實際可能要求進行相當多的操作,特别是在涉及繼承的時候。

(Bruce哥不要說我抄襲,借鑒借鑒哈)

第一句:

這句闡述的是jvm何時以及怎樣加載某個類。很顯然,根據這句話的表述,我們可以看出:當用new關鍵字來首次建立某對象,或者直接通路靜态的類方法或類字段時,jvm開始打算加載某個類(這裡的類就是那個Dog類,強烈要求下個版本換為Duck!)。然後jvm便通過預設或使用者自己設定的classpath來找到那個同名的class檔案,緊接着便發生了加載。

第二句:

加載的結果就是在jvm中産生了一個包含了該類所有資訊的Class對象。緊接着就對靜态的子產品進行了初始化。這裡就是在說,你做的所有關于靜态子產品的初始化工作都在這裡第一次,也是最後一次完成了——不論你是用的“static int duck = 250”的形式,還是用的靜态代碼塊的形式。

ps:

靜态代碼塊初始化

static int duck ;

static

{

duck = 250;

}

第三、四句:

這兩句話是前兩句話的注解:1.Java内對象是在堆記憶體裡産生的。2.而且在配置設定了供這個對象使用的記憶體後,這段記憶體裡的每個存儲單元都會被jvm清零(所達到的效果就是基本類型被置為0 或 0.0 或 false ,引用則被置為null)

要提醒的是,這兩句裡的動作都在一二句之前完成。否則會出現可笑的情形:不管你咋初始化,你最後都會郁悶的發現被歸零了。

第五句:

這句最沒營養了,就是個強調。

第六句:

我說說繼承中的初始化吧。

當你調用一個父類的子類,或許就是調用了這個子類的建構函數,jvm總會調用父類的建構函數來實作完整的初始化。

也就是說,調用這個子類,jvm會有規律的找他的父類。

如若這個父類又是某個父類的子類,則jvm還會繼續向上找尋父類,直到最終父類——Object類。

然後又在依次向下,調用各父類的建構方法來初始化它的直接子類——直到最終子類。這樣一來,啥子產品的初始化都不會落下了。為James Gosling 的智慧鼓掌!

二、android裡的3d效果

做人要幹脆,先來源碼:

Rotate3d 類:

package cn.com;

//導入相關類

import android.graphics.Camera;

import android.graphics.Matrix;

import android.view.animation.Animation;

import android.view.animation.Transformation;

//本類繼承了android裡面動畫的基類Animation(說白

//了也就是對四個基本動畫:alpha,scale,translate,rotate的綜合應用)

public class Rotate3d extends Animation {

private float mFromDegree;

private float mToDegree;

//有必要解釋下android内的圖像坐标系統:canvas坐标。

//原點位于螢幕中央,水準向左為x正方向,垂直向上為y正方向,垂直螢幕指向使用者則為z

//正方向

//下面的mCenterX,mCenterY則是後面Camera類要用到的“旋轉中心坐标”,結合canvas

//坐标的解釋應該不難了解

private float mCenterX;

private float mCenterY;

private float mLeft;

private float mTop;

//這個Camera類可不是android.hardware.Camera。本Camera是用來實作android中2d

//環境下簡單3d效果的類。而後者卻是android裡用來調用攝像頭硬體的類,相差大大着呢

private Camera mCamera;

private static final String TAG = "Rotate3d";

//構造方法,知了知了!!

public Rotate3d(float fromDegree, float toDegree, float left, float top,

float centerX, float centerY) {

this.mFromDegree = fromDegree;

this.mToDegree = toDegree;

this.mLeft = left;

this.mTop = top;

this.mCenterX = centerX;

this.mCenterY = centerY;

}

//下面幾個字首@Override字樣的方法是繼承Animation類後要重寫的方法。

//initialize方法大多是這個樣:調用父類的initialize方法實作初始化(很偷懶的重寫方法啊)

//同時你可以在這個方法内初始化一些本地的字段,例如這裡給字段裡的mCamera提供了一

//個執行個體的引用

@Override

public void initialize(int width, int height, int parentWidth,

int parentHeight) {

super.initialize(width, height, parentWidth, parentHeight);

mCamera = new Camera();

}

//這是一個回調函數,會在動畫執行期間不斷回調,通過細微的改變實作動畫效果(動畫本身

//就是一個又一個圖檔組合到一起的嘛)

//而這裡所謂的細微改變則是傳入的參數interpolatedTime的值的改變(從0.0到1.0,每次

//回調時會改變一次)

@Override

protected void applyTransformation(float interpolatedTime, Transformation t) {

final float FromDegree = mFromDegree;

//這裡利用那個參數細微的改變來實作圖檔相對于螢幕角度的逐漸變化

float degrees = FromDegree + (mToDegree - mFromDegree)

* interpolatedTime;

final float centerX = mCenterX;

final float centerY = mCenterY;

//怎麼還有矩陣呢?哈哈,不用納悶,3X3矩陣可是神通廣大的(用它可以抽象點的一系列行

//為:移動,旋轉...具體請看:http://www.moandroid.com/?p=1771 裡的介紹),這

//裡的Matrix類就是這樣的一個3X3矩陣的模拟類,内涵九個float字段

final Matrix matrix = t.getMatrix();

if (degrees <= -76.0f) {

degrees = -90.0f;

mCamera.save();

mCamera.rotateX(degrees);

mCamera.getMatrix(matrix);

mCamera.restore();

} else if (degrees >= 76.0f) {

degrees = 90.0f;

mCamera.save();

mCamera.rotateX(degrees);

mCamera.getMatrix(matrix);

mCamera.restore();

} else {

mCamera.save();

//

mCamera.translate(0, 0, centerY);

mCamera.rotateX(degrees);

mCamera.translate(0, 0, -centerY);

mCamera.getMatrix(matrix);

mCamera.restore();

}

//上面的代碼有些迷糊啊。恩,這樣了解,把Camera類的功能想象為操控正對螢幕的錄影機

//的功能類。結合canvas坐标,rotateX方法就是相對于x坐标旋轉。如果傳給rotateX的參

//數為正,那就是機位相對x軸向正角方向旋轉,那在錄影機裡看到的會是怎樣的呢?就是圖

//片向x軸負角方向旋轉啦!機位機位,一切都是機位。。。這樣想就好。

matrix.preTranslate(-centerX, -centerY);

matrix.postTranslate(centerX, centerY);

}

}

有了自定義動畫類Rotate3d,當然就有實作的類啦:

源碼如下:

package cn.com;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.ViewGroup;

import android.widget.Button;

public class Layout3D extends Activity {

private int mCenterX = 0;

private int mCenterY = 240;

private ViewGroup layout1;

private ViewGroup layout2;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

layout1 = (ViewGroup) findViewById(R.id.layout1);

Button b1 = (Button) findViewById(R.id.button1);

b1.setEnabled(true);

b1.setOnClickListener(new Button.OnClickListener() {

public void onClick(View v) {

leftMoveHandle();

v.setEnabled(false);

}

});

}

public void jumpToLayout1(Rotate3d leftAnimation) {

}

public void jumpToLayout2(Rotate3d rightAnimation) {

}

public void leftMoveHandle() {

Rotate3d leftAnimation = new Rotate3d(0, -90, 0, 0, mCenterX, mCenterY);

Rotate3d rightAnimation = new Rotate3d(90, 0, 0.0f, 0.0f, mCenterX,

mCenterY);

leftAnimation.setFillAfter(true);

leftAnimation.setDuration(1000);

rightAnimation.setFillAfter(true);

rightAnimation.setDuration(1000);

layout1.startAnimation(leftAnimation);

setContentView(R.layout.mylayout);

layout2 = (ViewGroup) findViewById(R.id.layout2);

layout2.startAnimation(rightAnimation);

Button b2 = (Button) findViewById(R.id.button2);

b2.setEnabled(true);

b2.setOnClickListener(new Button.OnClickListener() {

public void onClick(View v) {

rightMoveHandle();

}

});

}

public void rightMoveHandle() {

Rotate3d leftAnimation = new Rotate3d(0, 90, 0, 0, mCenterX, mCenterY);

Rotate3d rightAnimation = new Rotate3d(-90, 0, 0.0f, 0.0f, mCenterX,

mCenterY);

leftAnimation.setFillAfter(true);

leftAnimation.setDuration(1000);

rightAnimation.setFillAfter(true);

rightAnimation.setDuration(1000);

layout2.startAnimation(rightAnimation);

setContentView(R.layout.main);

layout1 = (ViewGroup) findViewById(R.id.layout1);

layout1.startAnimation(leftAnimation);

Button b1 = (Button) findViewById(R.id.button1);

b1.setEnabled(true);

b1.setOnClickListener(new Button.OnClickListener() {

public void onClick(View v) {

leftMoveHandle();

}

});

}

}

這段代碼較為簡單,是以就不多解釋啦。唯一要提醒的地方是private int mCenterY = 240;

想一想,手機的分辨率是320X480 , 240 = 480 X 0.5 , 而坐标原點在中心,mCenterY代表圖檔的旋轉軸。。。。

嗯,明了了。

ok,效果就不貼了,截圖挺麻煩的,總之很好就是啦。

好了,到這裡吧。謝謝圍觀,請多指教!