Blog On The Way`

Hackers On the way .

再看Java操作符

| Comments

刚开始学java的时候,我看的《java 语言的艺术与科学—计算机科学导论》,后来我开始看Oracel的《The Java turorials》,觉得这个讲得很清楚,当时我觉得看这个就很好,虽然也在这个教程里面看见了 The Java Language Specification》,也觉得这东西肯定很精确,不过没有进去看,主要是时间问题,当时觉得专注一点比较好。不过Turorials 确实比较浅一点,毕竟只是教程而已,教程只是教会你怎么使用—即HOW,而如果你想理解的精确(如WHY),就必须看其他的,甚至应该了解底层。 在看书或者文档之前,也许我要搞清楚这书(或者其他文档/资料)到底是定位,比如仅仅只是教程,又比如是精确的定义,又或者是其他教程加上个人理解。拿android来说,开发者页面有几个选项卡,
+ Training
+ API Guide
+ Reference
其中 trianing 会告诉你如何开始写安卓应用,但是点到即止。而API Guide 则对每个类和接口提供了详细说明,还包括了一些重要概念的说明与解释。 至于Reference 则是参考手册了,javadoc,针对代码 而写的注释。

好吧,开始正题。

再说操作符之前先看看java语言的数据类型。

java数据类型:

1. 原始数据类型

  • boolean 类型
  • 数值类型( numeric types)
    • 整数类型 (integer types)
      • byte
      • char
      • short
      • int
      • long
    • 浮点类型 (floating -point types)
      • float
      • double

2. 引用数据类型

  • array
  • Object

    3. null 类型

    空类型没有名字,可视为常量。




Java 为原始数据类型值定义了操作符(为 引用数据类型 String 定义了连接操作符 “+” )。操作符是什么东西,不过是一个符号表示,人来定义其意义,加上具体实现即可。看操作符根据类型来看最好,

操作符

1. 针对boolean 类型的操作符有:

+. 关系运算符 (==) 和 (!=) +. 逻辑补 (!) +. 逻辑与(&),逻辑异或(^), 逻辑或(|) +. 条件与(&&), 条件或(||) +. 三目条件运算符 ( ? :) +. 字符串连接运算符 (+) {连接字符串时,将boolean值装换为 true / false 的字符串}

2. 针对整数类型的操作符 Numeric 之 Integer Operations

  • 比较操作符

    • < , <= , > , >=
    • == , !=
  • 数学运算(结果为 int 或 long)

    • 一元正/负操作符: + , –
    • 乘/除/取余: * , / , %
    • 加/减:+ , –
    • 自增/自减 : ++ , —
    • 带符号左移/带符号右移/无符号右移: << , >> , >>>
    • 位补(bitwise complement): ~
    • 整型位操作符: & , ^ , |
  • 条件运算符
    • ? :
  • 强制类型转换 由一种整型转换到其他整型
  • 字符串连接操作符
    • 十进制值型字符串 如 “value:” + 0x80 >>>> value:128

其中需要注意的有:

  • 移位运算符:
    • n << s = n * power(2,s) (2的s 次方)
    • n >> s = n / power(2,s)
    • n >>> s (其中 2<<-s)是为了去掉符号位
      • n为正数 :n >>> s = ( n >> s )
      • n 为 int 型负数 : n >>> s = (n >> s) + (2<<-s) = (n >>s) + (2>>(31-s))
      • n 为 long 型负数: n >>> s = (n >> s) + (2<<-s) = (n>>s) + (2<<(63-s))

按位运算符 — ~, & , ^, |

字符串连接:字符串连接输出的是十进制值字符串

浮点数操作符

浮点数

Java 中的浮点数有两种,1. IEEE 754 单精度浮点数, 2. IEEE 754 双精度浮点数。 IEEE 浮点数的值有, 正负无穷, 有限数,正负零,NaN(Not-a number value), 除了NaN, IEEE浮点数是有序的,从最小的到最大的,
负无穷 》》 有限负数 》》 正负零 》》 有限负数 》》 负无穷

其中有限非零值都可以表示为: s * m * 2e-N+1 其中: s为 +1/-1 m < 2N e 位于Emax 和 Emin 之间 , Emin = –( 2K-1– 2 ) Emax= 2K-1-1 K , N 取决与浮点数属于那个浮点数集合。

下面这张表说明了单精度浮点数和双精度浮点数的K N 取值

浮点数 K N 取值
row float double
N 24 53
K 8 11
Emin -127 -1022
Emax 126 1023


其他说明:
  • 零: 0.0>-0.0 = false ; 0.0 == -0.0 = true ; 1.0/0.0 = 正无穷; 1.0/-0.0 = 负无穷
  • NaN: <, <=, >, >= , == 有一个操作数为NaN则结果为false, 但是 != 有一个操作数为NaN,则值为true
针对浮点数的操作符

+, -正负 +, –, *, /, % ++, —

==, >, >=, <, <=, != ? :

字符串连接

强制类型转换。

操作符优先级

Operator Precedence
Operators Precedence
postfix expr++ expr--
unary ++expr --expr +expr -expr ~ !
multiplicative * / %
additive + -
shift << >> >>>
relational < > <= >= instanceof
equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
ternary ? :
assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=


规律:

  • 赋值运算符及其各种组合优先级最低
  • 一元 > 二元 > 三元
  • 二元: 算数 > 移位 > 关系 (> Equality) > 按位运算 > 逻辑
  • 算数: 先乘除(包括余), 后加减
  • 按位: 与 > 异或 > 或
  • 逻辑: 与 > 或

结合性: 除赋值外,都是左结合

Android 序列化 – Parcelable

| Comments

序列化

  • 为什么要序列化?

    1. 永久性保存对象,保存对象的 字节序列 到本地文件中
    2. 通过序列化在网络中传递对象。
    3. 通过序列化在进程间传递对象。
  • 序列化: 将数据结构或者对象 state 转换成可以存储的格式(如文件,memory buffer,或者在网络上传输),之后再在相同的计算机或者不同的计算机环境中恢复。当生成的bits序列按 serilization 格式被重新读出时,它可以创建一个语义唯一(semantically identical) 的原始对象的克隆。
    序列化的过程也被叫做 deflating 或者 marshalling 。相反的操作则叫做 deserialization (也叫做 inflating 或者 unmarshalling )。

  • 序列化格式:

    • XML , 有常规的xml(human readable text-based encoding,可以用文本编辑器打开) 和 Binary xml。在20世纪,XML经常被用于Ajax网站应用的客户端和服务器之间的数据结构的异步传输。
    • JSON, 是一个较之于XML 更加轻量级的序列化格式,JSON 也普遍被用于web 应用的C/S通讯, JSON 基于JavaScript 语法格式,不过也支持其他编程语言。
    • YAML, 高效的JSON超集,包括了一些特性使得它拥有更加强大的序列化功能,对人更加友好,拥有更好的潜在兼容性。在看jekyll 时发现了这个: YAML Ain’t Markup Language
    • MAC OS X Cocoa..

  • 编程语言支持

    • Java — java.io.Serializable interface …

参考:wiki百科 Serilization



安卓序列化

  • Android 序列化的两种方法
    1. Serializable 接口
    2. Parcelable 接口

实现 Parcelable 接口实现安卓序列化

  • implemnts Parceable
  • 需要序列化的类必须有一个 static field : CREATEOR ( CREATEOR 是一个实现了Parcelable.Creator 接口的对象)

代码示例:

  • 目的: 实现 Parcelable 接口用于进程间(?)传递对象。程序的运行流程是: 点击MyParcelable 的button ,启动ActivityB 并将一个Person 实例传递过去,然后再再ActivityB 中将收到的Person 对象的信息显示在Textview 上。

  • 主要结构: 一个Project, 建两个Activity— MyParcelable,ActivityB 。 MyParcelable 布局中添加一个button, 为Button 添加属性:
    android:onClick=“onClick”
    ActivityB 的xml 布局里添加一个TextView。
    一个 Person 类实现 Parcelable 接口。

  • 代码:

MyParcelable :

public class MyParcelable extends Activity implements OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn1:
            Intent intent = new Intent();
            intent.setClass(this, ActivityB.class);
            Bundle extras = new Bundle();
            extras.putParcelable(Person.PARCELABLE_KEY, new Person("Libelosophy", 100));
            intent.putExtras(extras);
            startActivity(intent);
        }
    }
}

ActivityB :

public class ActivityB extends Activity {
    private TextView tv = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_activity_b);
        tv = (TextView) findViewById(R.id.textview);

        Person person = getIntent().getExtras().getParcelable(Person.PARCELABLE_KEY);
        String person_info = "Name: " + person.getmName() 
                                + "\n Age: " + person.getmAge();

        tv.setText(person_info);

        }       
}

Person :

public class Person  implements Parcelable {
    public static final String PARCELABLE_KEY = "PersonParcelableObject";

    private String mName;
    private int mAge;


    public String getmName() {
        return mName;
    }

    public void setmName(String mName) {
        this.mName = mName;
    }

    public int getmAge() {
        return mAge;
    }

    public void setmAge(int mAge) {
        this.mAge = mAge;
    }

    Person(String name, int age) {
        setmName(name);
        setmAge(age);
    }



    private Person(Parcel in) {

        setmName(in.readString());
        setmAge(in.readInt());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(getmName());
        dest.writeInt(getmAge());
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

        @Override
        public Person createFromParcel(Parcel source) {

            return new Person(source);
        }

        @Override
        public Person[] newArray(int size) {

            return new Person[size];
        }
    };

}

运行结果: 如预期。

实例

project简单介绍: OIFileManager一个文件浏览器。 FileHolder 类包含文件基本信息(文件,扩展名…), FileHolderAdapter 是用来关联View 和 file列表数据的Adapter, FileListFragment 则是界面及执行体。

首先看看FileHolder 里面的代码,FileHolder 实现了 Parcelable 以支持序列化 ,比较熟悉了:

// FileHolder.java 不完整代码
public class FileHolder implements Parcelable, Comparable<FileHolder> {
    private File mFile;
    private Drawable mIcon;
    private String mMimeType = "";
    private Context mContext;
    private String mExtension;

    // 。。。。。。

    // 用 Parcel 中保存的对象来够造FileHolder对像 的构造函数 
    public FileHolder(Parcel in){
        mFile = new File(in.readString());
        mMimeType = in.readString();
        mExtension = in.readString();
    }

    // 序列化

    @Override
    public int describeContents() {
        return 0;
    }

    // 可以看见向 Parcel 只写入了三条String : 文件路径, Mimetype, 扩展名
    // [可以直接用 dest.writeSerializable() 将mFile写到Parcel] ? [怎么写] : [为什么不这么用]
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mFile.getAbsolutePath());
        dest.writeString(mMimeType);
        dest.writeString(mExtension);
    }

    public static final Parcelable.Creator<FileHolder> CREATOR = new Parcelable.Creator<FileHolder>() {
        public FileHolder createFromParcel(Parcel in) {
            return new FileHolder(in);
        }

        public FileHolder[] newArray(int size) {
            return new FileHolder[size];
        }
        };
}

在 FileListFragment 中 :

// FileListFragment.java 不完整代码, 函数也被删去了部分代码

private static final String INSTANCE_STATE_PATH = "path";
private static final String INSTANCE_STATE_FILES = "files";
private static final String TAG = "FileListFragment";
File mPreviousDirectory = null;


protected FileHolderListAdapter mAdapter;
protected DirectoryScanner mScanner; //目录扫描器,扫描目录文件列表并将列表作为消息发送的线程
protected ArrayList<FileHolder> mFiles = new ArrayList<FileHolder>();
private String mPath;
private String mFilename;

private ViewFlipper mFlipper;
private File mCurrentDirectory;

// onSaveInstanceState(Bundle) 回调函数用来保存fragment 的state 用于重新构造fragment, 
//  bundle 所放的state 在函数onCreate , onCreateView onActivityCreate 中可用 
// 当然还应该有onViewCreated ,
@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putString(INSTANCE_STATE_PATH, mPath); 


    // ArrayList 实现了 Serialization 接口, FileHolder 实现了Parcelable 接口。
    // Inserts a List of Parcelable values into the mapping of this Bundle
    outState.putParcelableArrayList(INSTANCE_STATE_FILES, mFiles); // 就这个调用了。
}

// 
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {

    // 删掉了一些无关 主题的代码

    // Get arguments
    if (savedInstanceState == null) {
        // 如果没有保存过Fragment 的 实例, 则说明是第一次,从启动时的设置参数中取出path 和filename
        mPath = getArguments().getString(FileManagerIntents.EXTRA_DIR_PATH);


        mFilename = getArguments().getString(
                FileManagerIntents.EXTRA_FILENAME);
    } else { // 否则直接从保存的bundle 中恢复state
        mPath = savedInstanceState.getString(INSTANCE_STATE_PATH);
        mFiles = savedInstanceState
                .getParcelableArrayList(INSTANCE_STATE_FILES);
    }
    pathCheckAndFix();
    renewScanner();

    // 设置数据源,及关联到 Fragment ( ? 一个 ListView 在哪?? )
    Log.v(TAG, "设置数据源, FileHolderAdapter关联到 FileListFragment");
    mAdapter = new FileHolderListAdapter(mFiles, getActivity());

    setListAdapter(mAdapter);
    mScanner.start();

}

Unix Programming

| Comments

书籍

  • Adcanced Progamming in the UNIX Environment (Second Edition) —W.Richard Stevens , Stephen A. Rago

  • Advanced UNIX Programming (Second Edition) —Marc J. Rochking

  • Linux 程序员手册 通过 man 命令可查看

参考

  1. [www.unix.org] (http://www.unix.org)
    下载好的2013版html susv4
    04版 susv3
    suv3在线查看


2. c 语言: C A reference manual 3. c++ The C++ Programming Language

UNIX 高级环境编程的内容

  1. 系统调用接口

  2. (标准C)库函数

两本书中,有一本只准备讲系统调用,而故意忽略标准C库函数.那么系统掉调用和库函数的区别在哪儿呢?

  • 各种版本的UNIX 实现都提供了定义明确、数量有限、可直接进入内核的入口点。这些入口点就称为系统调用(System Call)
  • UNIX 为每个系统调用在标准C库中设置一个具有同样名字的函数,这些函数可能会调用一个或多个系统调用。
  • 系统调用会产生两次模式切换(用户—内核,内核拥有最高级别权限),但是不一定会产生上下文切换?wiki
  • 而库函数调用本身不会产生模式切换,因为它工作在用户模式.不过如果该库函数调用系统调用,则会产生.
  • 系统调用通常提供一种最小接口,而库函数通常提供比较复杂的功能.
  • POSIX 标准中包含 ISO C.
  • 几个例子说明系统调用和库函数的区别:(UNIX高级环境编程)
    1. malloc 存储器分配函数调用了 sbrk 系统调用实现了一种特定的存储分配方式,不过你也可以用 sbrk 实现其他的存储分配方式
    2. UNIX 系统只提供一个获取时间的系统调用,该系统调用返回国际标准时间 1970.1.1 零点以来经过的所有秒数,而各种库函数则可以对这个数值进行各种解释,如转换为人类可读的形式,或者夏時制算法等等.

unix 标准化

  • ISO C

ISO: International Organizaition for Standardization 国际标准化组

提供C 程序的可移植性,使其适合于大量不同操作系统 定义了C 程序语言的设计语法和语义 及 其标准库

  • IEEE POSIX

IEEE : Institute of Electrical and Electronics Engineers 电子与电气工程师协会

POSIX: Portable Operating System Interface 可移植操作系统接口 X表示对UNIX API 的传承

提高应用程序在各UNIX 系统环境之间的可移植性. 定义了遵从POSIX 的操作系统所必须提供的各种服务.

  • Single UNIX Specification 单一UNIX 规范 ,是POSIX.1 标准的一个超集. 亦称(XSI) X/Open System Interface

UNIX 基础之 文件系统

  • 文件类别:
    • 常规文件
    • 目录
    • 符号连接
    • 特殊文件
    • 命名管道(FIFO)
    • 套接字文件(socket)

文件 I/O (不带缓冲的I/O)

不带缓冲: 每个read 和 write 都调用内核中的一个系统调用

  • 内容:
    • open
    • create
    • close
    • lseek
    • read
    • write
    • dup dup2
    • sync fsync fdatasync
    • fcntl
    • ioctl

文件描述符
内核使用 文件描述符 来引用打开的文件,文件描述符是一个整数
— 当系统 打开一个现有文件或者创建一个新的文件时(open ,create),内核向进程返回一个文件描述符。
— 当读或写一个文件时,将标识一个文件的文件描述符作为参数传递给read 或 write

open


#inlcude <fcntl.h>

int open(const char * path, int oflag, .../* mode_t mode */);
int openat(int fd, const char * path, int oflag, ...);// relative to directory file descriptor

文件和文件描述符之间的连接桥梁,它会创建一个打开的文件描述符,该文件描述符关联这个打开的文件。文件描述符被用于其他IO 功能中引用文件。 默认的文件偏移别设置在文件的开始处

path — points to a pathname nameing the file
oflag — file status flags and file access modes of the open file description shall be set according to the value of oflag

Vlaues of oflags (bitwise-inclusive OR of flags , defined in fcntl.h)
Application shall specify exactly one of the first five(susv4) or three(susv3) values (file access modes) below in the value of oflag:

  • 三个必选其一的 access mode :

    • O_RDONLY
    • O_RDWR — Open for reading and writing, The result is undefined if this flag is applied to a FIFO(命名管道)
    • O_WRONLY
  • add in susv4

    • O_EXEC — Open for execute only (non-directory files), the result is unspecified if this flag is applied to a directory.
    • O_SEARCH — open directory for search only, The result is unspecified if the flag is applied to a non-directory file.
  • 可选组合:

    • O_APPEND — if set , the file offset shall be set to the end of the file prior to each write. (如果设置的话, 文件偏移会被设置到文件末尾)
    • O_CLOEXEC — if set, FD_CLOEXEC flag for the new file descriptor shall be set
    • O_CREATE — If file exists, this flag has no effect except as noted under O_EXCL below. Otherwise, the file shall be create; the user ID of the file shall be set to the effective user ID of the process ; the group ID of the file shall be set to the group ID of the file’s parent directory or to the effective group ID of the process; and the access permisssion bits (see sys/stat.h) of the file mode shall be set to the value of the argument following oflag taken as type mode_t modified as follow: a bitwise AND is performed on the file-mode bits and the corresponding bits in the complement of the process’s file mode bits creationg mask is set are cleared . When bits other than the file permission bits are set, the effect if unspecified. the argument following the oflag does not affect whether the file is open for reading, writing, or for both. Implementions shall provide a way to initailize the file’s group ID to the group ID of the parent directory.Implementations may , but need not , provider an implementation-defined way to initialize the file’s group ID to the effective group ID of the calling process.
    • O_DIRECTORY — IF path resolves to a non-directory file , fail and set errno to [ENOTDIR]
    • O_DSYNC — Write I/O operations on the file descriptor shall complete ad defined by synchronized I/O data integrity completion. 使每次I/O 等待物理I/O 操作完成,但是如果写操作并不影响读取刚写入的数据,则不等待文件属性被更新。
    • O_EXCL —

How to Work With Git

| Comments

如何使用GIT

  • 註冊: 到 github 註冊一個帳號。
  • 在你的github 頁面新建一個 repository

create repo

點擊中間那個帶有 + 的圖標,爲repo 取名,添加描述,確認。

假設repo 名爲project

  • 安裝 git :

  • Windows : 下載 msysgit

  • Linux :

    • ubuntu :

      sudo apt-get install git

  • git 本地操作。

window 打開git-bash.bat, linux 打開終端。執行以下操作:

mkdir workspace
cd workspace
git clone https://github.com/libelosophy/AndroidFileExplorer.git 
cd AndroidFileExplorer
git remote add origin https://github.com/*你的用戶名*/project.git # project 爲repo 名
git add .
git commit -m "提交說明,可以隨便寫“

# 代碼push 到你的 github 遠程repo 上。
git push origin master 

然後在eclipse 中導入項目,目錄選擇AndroidFileExplorer. 完成後進行開發。

Ubuntu Install & Use Emacs24

| Comments

1. Ubuntu install emacs24 from source code

# get source code       
wget http://mirrors.ustc.edu.cn/gnu/emacs/emacs-24.3.tar.xz

# extract
tar -xvf emacs-24.3.tar.xz
cd emac-24.3

# install x toolkit support lib and other (libtinfo is required)
sudo apt-get install libgtk2.0-dev
sudo apt-get install libtinfo-dev

# configure 
./configure --with-xpm=no --with-jpeg=no --with-gif=no --with-tiff=no

# make 
make 

# Test if emacs works
src/emacs -Q

# install 
sudo make install 

# Test if install is succed
emacs

# clean the output
make clean

# save the source code 
sudo mv emacs-24.3 /usr/local/src

2. Basic usage

  • 一般用法 CONTROL + <chr> 两种 CONTROL :
    • CTRL /CTL :Ctrl
    • META: Meta / Edit / Alt
  • 退出 编辑的session : C-c C-x
  • 下一页: C-v (View next page)
  • 上一页: M-v
  • 页内移动:
    1. previous : C-p 前一行
    2. next : C-n 后一行
    3. backward : C-b 前移
    4. forword : C-f 后移 中央聚焦: C-l 使光标所在处显示在屏幕中央
    5. 字移动 :M-b 以字为为单位向后移动(中文是移到下个标点,下同) : M-f word forward

    6. C-a, C-e : 移动到行开始,行结束

    7. M-a, M-e : 移动到上一句,下一句

    8. M-< : 文字开始 Alt+ shift + ,

    9. M-> : 文字结束 Alt+ shift + .

  • 重复: C-u 数字 C-<chr> 例外: C-u <num> C-v/M-v 是卷动 num 行,而不是 num 页

  • 停止/取消数字参数/ 撤销ESC: C-g