`
soboer
  • 浏览: 1310070 次
文章分类
社区版块
存档分类
最新评论

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;

/** Called when the activity is first created. */

@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,效果就不贴了,截图挺麻烦的,总之很好就是啦。




好了,到这里吧。谢谢围观,请多指教!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics