2008年7月3日星期四

浅析Java内部类与嵌套类

浅析Java内部类与嵌套类

Abstraction:

本文描述了Java语言的嵌入类、内部类的具体分类和行为表现。

1 概述

我们知道,Java是一种完全的面向对象的语言,作为对象的灵魂,类的种类是多种多样的。类大致可以分外部类和内部类两种,外部类就是我们通常使用的类,而内部类的使用要比外部类少的多,最常见的是GUI事件侦听器。内部类的应用虽然不多,但是如果能够有效的使用内部类,能达到事半功倍的效果。废话不多说,下面开始:

2 内部类和嵌套类:

要讨论内部类和嵌套类,首先要分清他们两者的区别于联系。

首先,内部类(Inner Classes)和嵌套类(Nested Classes)是指在一个类里面定义的另一个类。其次无论是内部类还是嵌套类,在编译时都被当作一个独立的整体。对于访问他们的其他对象来说(假如他们对这个类来说是可见的)他们的使用和我们通常用的类是一样的。

但是,内部类和嵌套类的区别在于:

1. 嵌套类是静态的,而内部类不是,也就是说嵌套类的实例化不需要外部类的实例。但是内部类是需要这个实例的。

2. 嵌套类可以任意声明静态成员,内部类不允许声明除了编译时常量以外的任何静态成员。这一限制也适用于静态初始化函数。

3. 嵌套类都是命名的,匿名的类声明不能声明运行时静态成员(不管声明是不是静态的)。

注意:类内部声明的接口都属于嵌入类。

下面我们来分别讨论一下他们的具体行为表现。

3 内部类

内部类是指在一个类里面以非静态形式声明的另一个类。内部类的实例化需要外部实例的存在。一个类可以拥有多个内部类,一个外部实例可以拥有多个内部类的实例。但是内部类有且只有一个外部实例,并且在实例化时就已经指定,无法更改。

3.1 内部类的分类

内部类根据访问权限不同可以分为以下一种类型:普通内部类和局部内部类。

普通内部类和局部内部类主要的区别在于作用域和访问权限的不同,普通内部类可以被所有人访问(只要访问控制符允许),而局部内部类的作用域更像一个变量,只能在定义它的函数内部被使用,其他人是无法使用这个类的。而且局部类可以访问定义它的函数中的final变量。

根据声明方式不同又可以分为:命名内部类和匿名内部类。命名内部类和匿名内部类的区别在于:

首先,命名类可以抽象的。匿名类不能为抽象,事实上,匿名内部类在编译时被隐形的声明为最终的(final)。

其次,命名类声明可以继承一个父类并实现多个接口,匿名类只能有一个父类(或者接口)。

再次,命名类可以被多次实例化,而匿名类只能在定义时被实例化一次。

最后,命名类可以声明多个构造函数并控制访问哪一个父类的构造函数,匿名类无法声明构造函数。

下面分别描述这些区别:

3.2 普通内部类

普通内部类是指在类成员定义中定义的类,这些类可以拥有访问控制符(public, private等)。如果访问控释符允许,则这些类可以被外面直接应用。普通命名内部类可以声明为一个接口,或者是抽象的。嵌入类其实是特殊的普通内部类,但由于其特殊性,故在下面独立讨论。

3.2.1 声明:

3.2.1.1 命名类:

class OuterClass{

//Outer class deflation
class InnerNamedClass{
//Inner class definition

}
}

3.2.1.2 匿名类:

声明匿名类时,可以使用一个类或者接口作为他的父类。

class OuterClass{
//Outer class deflation
Object unnamedObject = new Object(){
//Inner class definition
}
}

3.2.2 实例化:

3.2.2.1 命名类:

外部或静态方法:

OuterClass outerObject = new OuterClass();
OuterClass.InnerNamedClass innerObject = outerObject.new InnerNamedClass();

内部:

InnerNamedClass innerObject = new InnerNamedClass();

3.2.2.2 匿名类:

定义时即完成实例化

3.2.3 访问权限:

3.2.3.1 内部实例对外部实例的访问权限为:

外部类定义或继承的所有字段

3.2.3.2 外部实例对内部实例的访问权限为:

内部类定义或继承的所有字段

3.2.3.3 其他对象对内部实例的访问权限为:

若内部类不可见,则只能访问其超类定义的字段

若内部类可见,则可访问内部实例的非私有字段,具体情况与通常的类类似

3.2.4 备注:

内部类的外部实例是在构造时作为参数传给构造函数的,在SUN JDK中,保存外部实例的字段通常被声明为:

final OutterClass this$0;

3.3 局部内部类

局部内部类,是指在函数体内声明的类,这种类是局域性的,只在函数内声明后有效,他最大的特点是:可以访问定义它的函数中的final变量。

3.3.1 声明:

3.3.1.1 命名类:

class OuterClass{
//Outer class deflation
void aMethod(){
class InnerNamedClass{
//Inner class definition
}
}
}

3.3.1.2 匿名类:

class OuterClass{
//Outer class deflation
void aMethod(){
Object unnamedObject = new Object(){
//Inner class definition
}
}
}

3.3.2 实例化:

3.3.2.1 命名类:

局部类的作用域仅限定义该类的方法中,无法在外部实例化或访问,实例化方法与通常类相同

3.3.2.2 匿名类:

定义时即完成实例化

3.3.3 访问权限:

3.3.3.1 内部实例对外部实例的访问权限为:

外部类定义或继承的所有字段

定义该内部类的方法在定义类之前所定义的所有final变量

3.3.3.2 外部实例对内部实例的访问权限为:

在定义该内部类的方法中可以访问内部类定义或继承的所有字段

在外部实例的其他字段中只能访问其超类定义的字段

3.3.3.3 其他对象对内部实例的访问权限为:

只能访问其超类定义的字段

3.3.4 备注:

当试图访问一个final变量时,编译器实际上把该变量的值赋值给内部类的一个隐含字段中。编译器会自动的在构造函数中添加相应的参数。在SUN JDK中,这个隐含字段通常被命名为:val$varname

3.4 使用内部类的注意事项:

本节包括了一些使用内部类时需要注意的事项,这些事项对所有内部类都适用。

3.4.1 静态成员

首先需要注意的是,内部类不能非常量声明静态成员,任何静态成员的声明都会被当成编译错误,例如:

InnerClasses.java:12: 内部类不能有静态声明

static String a;

^

1 错误

先要了解更加详细的信息,请参考附录A

3.4.2 访问外部实例

要在一个内部实例中访问外部实例,请使用:

OuterClass.this

3.4.3 字段覆盖

在内部类中声明的与外部类同签名的字段将覆盖外部字段,要访问外部字段请使用外部实例对象前缀。

OuterClass.this.field

OuterClass.this.Method();

4 嵌套类

嵌套类(Nested Classes)其实是普通内部类的一种特殊形式,首先它的声明是静态的,这就表示了这个类不需要外部实例。也表示了他不能访问外部类的实例字段。但是相应的,嵌套类可以拥有非常量静态成员。事实上,JDK通常把嵌套类当成一个具有特殊名字的独立类。

另外,嵌套类还拥有一种特殊形式:匿名嵌套类。前面说过,匿名类都是内部类,但是匿名嵌套类是一个特例,从理论上讲,他既不属于嵌套类,也不属于内部类。匿名嵌套类 不允许拥有非常量静态成员,但是他也没有外部实例供访问。

4.1 声明:

4.1.1 命名类:

class OuterClass{

//Outer class deflation
static class StaticInnerNamedClass{
//Inner class definition

}
}

4.1.2 匿名类:

class OuterClass{
//Outer class deflation
static Object unnamedObject = new Object(){
//Inner class definition
}
}

4.2 实例化

4.2.1 内部

StaticInnerNamedClass staticInnerNamedObject = new StaticInnerNamedClass();

4.2.2 外部

OuterClass.StaticInnerNamedClass staticInnerNamedObject = new OuterClass.StaticInnerNamedClass();

4.3 访问权限:

4.3.1 内部实例对外部实例的访问权限为:

外部类定义或继承的所有静态字段

4.3.2 外部实例对内部实例的访问权限为:

与通常内部类相同

4.3.3 其他对象对内部实例的访问权限为:

与通常内部类相同

A. 附录(Appendix)

A) 为什么内部类不能声明静态成员?

关于这个问题,MS JLS没有给出一个明确的答案(还是我没找到么?)。后来我在Usenet的新闻组上发贴子问了一下,结果大概是这样的:

1) 匿名类使用非常量静态成员是不必要的,因为匿名类只有一个实例

2) 命名内部类如果允许使用静态 的话会使内部类显得过分独立,应该尽量使用外部类的设施。

(原帖见https://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/0f109738f2f089d9?hl=en#d61250f96cf8e96e)

Why inner classes can not have static members?

bearice@gmail.com

Feb 4, 10:15 pm

as title.

Lew

Feb 4, 11:07 pm

> bear...@gmail.com wrote:

> as title.

Cultural note: It's considered polite to repeat the question inside the body of the post to facilitate others' ability to read the conversation.

Inner classes can have static members, provided such members are compile-time constants.

Asking "why" the language specifies something is an exercise in telepathy, unless the language designers left some notes or blog entries or white papers behind explaining the rational, which they might have done. GIYF.

I know that static members of inner classes would confuse me. Would such a member only be static within the context of the immediately enclosing instance of some instances of the inner class, or would it apply to all instances of the inner class?

The problem is that inner classes are (generally) instantiated within an instance of their enclosing class. Inner classes are not "static" enough on their own for me to be comfortable with a "static" that operates across all enclosing instance contexts. I suppose I could get used to it if Java were defined that way, but it isn't. It's defined to make inner classes very dependent on their enclosing instances.

If you want static members, use non-inner nested classes, or avoid nested classes altogether.

Why is a static member of an inner class necessary for you? Why is an alternative idiom not acceptable?

Lew

Markus Tazl

Feb 4, 11:18 pm

wrote:

> As title.

Wow, a question in shorthand? :-)

Anyway, Sun's Docs are your friend. Explained here in detail:

http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html, see

Topic: "Inner classes" at the end of the page

Best regards

Markus Tazl

bearice@gmail.com

Feb 5, 4:53 am

- Quoted text -

I see, sorry for my impolite way of asking. And thank all of you for answering me.

I'm not really need a static member in an inner class. just very curious about it when the complier tells me it is an error.

Thanks again.

Lew

Feb 5, 8:38 am

Well, the simple answer is because that's the way it's defined for the language. The rules explicitly allow only compile-time constants to be static members of inner classes. Non-inner nested classes do not have this restriction.

> Inner classes may not declare static initializers (§8.7) or member interfaces.

> Inner classes may not declare static members, unless they are compile-time constant fields (§15.28). ...

> Nested classes that are not inner classes may declare static members freely, in accordance with the usual rules of the Java programming language.

In practice the restriction causes no difficulties. If anything, it makes inner classes easier to deal with, as one can conceptualize the inner class as "belonging" entirely to the enclosing instances that instantiate it without wondering if static members should differ between different enclosing instances.

Language designers always face interesting decisions like this, such as what the value of the remainder operator '%' should be when the denominator is negative. Sometimes they get it wrong, as many feel Java did by not (yet) making generics reifiable. I have never encountered an authoritative explanation for why inner classes in Java cannot have non-compile-time-constant static members; OTOH I've never encountered a situation where the restriction caused trouble.

Inner classes are an odd duck anyway. They're useful for sure, because having a class than can access the members (even private ones) of its enclosing class instance sure helps out - it mitigates the lack of closures, for example.

However, one should always consider using a non-inner nested class or non-public top-level class before creating an inner class that does not need such access.

--

Lew

da...@dagon.net

Feb 5, 9:01 am

bear...@gmail.com wrote:

>Why inner classes can not have static members?

Lew wrote:

>Inner classes can have static members, provided such members are compile-time constants.

Static inner classes can have static members without such a restriction. This is legal:

class Test {

static class Foo {

static int a;

public static void setA(int newA) {

a = newA;

}

}

}

The difference between a static and non-static inner class is important. A static inner class is a fairly normal class, and behaves very similarly to other outer classes. A non-static inner class has an implicit pointer to an instance of it's enclosing class, so doesn't really have a static context to execute in.

Note: anonymous inner classes are always non-static.

--

Lew

Daniel Pitts

Feb 5, 9:57 am

Mark Rafn wrote:

The difference between a static and non-static inner class is important. A static inner class is a fairly normal class, and behaves very similarly to other outer classes. A non-static inner class has an implicit pointer to an instance of it's enclosing class, so doesn't really have a static context to execute in

Note: anonymous inner classes are always non-static.

I actually believe that's called a nested class and has different semantics.

Lew

Feb 5, 11:19 am

Daniel Pitts wrote:

> I actually believe that's called a nested class and has different semantics.

"Static inner class" is a contradiction. Inner classes are never static, in that they are *defined* as nested classes that do not use the "static" keyword.

Nested classes comprise both inner classes and static nested classes.

The relevant section of the JLS is linked up thread.

--

Lew

B) 内部类与嵌套类的命名规则

内部类和嵌套类在编译时被分开成独立的类,编译器对这些独立的类有相应的命名规则,下面就来描述一下这些规则:

B.1匿名类的命名规则

所有的匿名类统一按下列规则重命名:

$

其中,ID是这个匿名类在外部类中出现的位置,例如第一个匿名类就是1,第二个就是2。

B.2 命名类的命名规则

命名类重命名规则为:

$

其中InnerClass为内部类的类名

B.3 局部命名类的命名规则

局部命名类的命名规则为:

$

其中,ID是同名的局部类在外部类中出现的位置,例如第一个就是1,第二个就是2,InnerClass为内部类的类名

C) 一个完整的例子

interface PublicPrint{
void pubPrint();
}
class OuterClass{
public static final void print(String str){System.out.println(str);}
public String pubStr = "public string";
private String prvStr = "private string";
public static String staPubStr = "static public string";
private static String staPrvStr = "static private string";
//命名内部类 OuterClass$InnerNamedClass
public class InnerNamedClass implements PublicPrint{
public void pubPrint(){
print(getClass().getName());
print(pubStr);
print(prvStr);
print(staPubStr);
print(staPrvStr);
}
}
//匿名内部类 OuterClass$1
public PublicPrint innerUnnamedObject = new PublicPrint(){
public void pubPrint(){
print(getClass().getName());
print(pubStr);
print(prvStr);
print(staPubStr);
print(staPrvStr);
}
};
//命名嵌套类 OuterClass$StaticInnerNamedClass
public static class StaticInnerNamedClass implements PublicPrint{
public void pubPrint(){
print(getClass().getName());
print(staPubStr);
print(staPrvStr);
}
}
//匿名嵌套类 OuterClass$2
public static PublicPrint staticInnerUnnamedObject = new PublicPrint(){
public void pubPrint(){
print(getClass().getName());
print(staPubStr);
print(staPrvStr);
}
};
public PublicPrint defineNamedEmbedClass(final String arg){
//命名局部类 OuterClass$1InnerEmbedNamedClass
class InnerEmbedNamedClass implements PublicPrint{
public void pubPrint(){
print(getClass().getName());
print(pubStr);
print(prvStr);
print(staPubStr);
print(staPrvStr);
print(arg);
}
}
PublicPrint innerEmbedNamedObject = new InnerEmbedNamedClass();
//innerEmbedNamedObject.pubPrint();
return innerEmbedNamedObject;
}
public PublicPrint defineUnnamedEmbedClass(final String arg){
//匿名局部类 OuterClass$3
PublicPrint innerEmbedUnnamedObject = new PublicPrint(){
public void pubPrint(){
print(getClass().getName());
print(pubStr);
print(prvStr);
print(staPubStr);
print(staPrvStr);
print(arg);
}
};
//innerEmbedNamedObject.pubPrint();
return innerEmbedUnnamedObject;
}
}
class Runner{
public static void main(String[] args){
//外部实例
OuterClass outerObject = new OuterClass();
//命名内部类
OuterClass.InnerNamedClass innerObject = outerObject.new InnerNamedClass();
innerObject.pubPrint();
//匿名内部类
outerObject.innerUnnamedObject.pubPrint();
//命名嵌入类
OuterClass.StaticInnerNamedClass staticInnerNamedObject = new OuterClass.StaticInnerNamedClass();
staticInnerNamedObject.pubPrint();
//匿名嵌入类
OuterClass.staticInnerUnnamedObject.pubPrint();
//命名局部类
PublicPrint innerEmbedNamedObject = outerObject.defineNamedEmbedClass("Hello");
innerEmbedNamedObject.pubPrint();
//匿名局部类
PublicPrint innerEmbedUnnamedObject = outerObject.defineUnnamedEmbedClass("World");
innerEmbedUnnamedObject.pubPrint();
}
}

D) 参考文档

JLS: <>

HCJ: <>

E) 版权声明

Mails referenced in Appendix A belong to their authors.

Java TM, Sun, are trade mark of Sun Microsystems Corp.

This document is released under CDDL.

Copy rights © 2008 Bearice [MDSA Group]

JNI中的中文处理

大树从网上搜索的-,-仅供收藏。

char* jstringToWindows( JNIEnv *env, jstring jstr )
{
int length = (*env)->GetStringLength(env,jstr );
const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 );
char* rtn = (char*)malloc( length*2+1 );
int size = 0;
size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
if( size <= 0 )
return NULL;
(*env)->ReleaseStringChars(env,jstr, jcstr );
rtn[size] = 0;
return rtn;
}

jstring WindowsTojstring( JNIEnv* env, char* str )
{
jstring rtn = 0;
int slen = strlen(str);
unsigned short* buffer = 0;
if( slen == 0 )
rtn = (*env)->NewStringUTF(env,str );
else
{
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
buffer = malloc( length*2 + 1 );
if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
rtn = (*env)->NewString( env, (jchar*)buffer, length );
}
if( buffer )
free( buffer );
return rtn;
}

2008年6月30日星期一

测试

不知道怎么回事,用word跟新时虽然网站上有内容但是word依然提示出错……

2008年6月29日星期日

2008年6月26日星期四

Java的超链接处理问题

最近为了这个Blog可谓麻烦死某熊……恩,今天写点有用的内容。
我们知道JEditPanel是支持HTML排版的,而HTML一个很重要的特性就是超链接,那么怎么在程序中处理那些超链接呢?答案是使用javax.swing.event.HyperlinkListener。这个监听器在超链接被触发时调用(例如鼠标进入,鼠标离开和点击)。集体的用法可以在JavaDOC中查到,这里就给出一个示例代码,这个函数返回的监听器将在外部浏览器打开指定的链接,链接必须包括http://

public HyperlinkListener createHyperLinkListener() {
return new HyperlinkListener() {

public void hyperlinkUpdate(HyperlinkEvent e) {
System.out.println(e);
if (e.getEventType() == HyperlinkEvent.EventType.ENTERED) {
((JEditorPane) e.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else if (e.getEventType() == HyperlinkEvent.EventType.EXITED) {
((JEditorPane) e.getSource()).setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} else if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
Desktop.getDesktop().browse(e.getURL().toURI());
} catch (Exception ex) {
Logger.getLogger(HTMLServerMessagePanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
};
}

2008年6月25日星期三

代码高亮测试


/*
* Copyrights (C) 2008 Bearice (Bearice@Gmail.com)
* Release under GNU/GPL Version 2.
*/
package cn.bearice.ipcontroller.client.core.remote.guet;

import cn.bearice.java.security.Account;
import cn.bearice.ipcontroller.controller.ControllerServer;
import cn.bearice.ipcontroller.RemoteServer;
import cn.bearice.ipcontroller.events.ServerStatusChangeListerer;
import cn.bearice.java.util.listener.*;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.login.AccountException;
import javax.security.auth.login.AccountLockedException;
import javax.security.auth.login.AccountNotFoundException;

/**
*
* @author Bearice
*/
public class GUET_UDPControllerServer implements ControllerServer {

public static final int STAT_NOT_LOGED_ON = 0;
public static final int STAT_LOGED_ON = 2;
public static final int STAT_LOGON_PENDDING = 1;
private static final Method statusChangedMethod;


static {
try {
statusChangedMethod = ServerStatusChangeListerer.class.getDeclaredMethod(
"serverStatusChanged",
new Class[]{
RemoteServer.class,
int.class,
int.class
});
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}

class StatusChangeListenerSupport extends ListenerSupport {

void fireStatusChanged(int before, int after) {
this.fireEventAsync(statusChangedMethod, GUET_UDPControllerServer.this, before, after);
}
}
public static final int CLIENT_LISTEN_PORT = 26000;
StatusChangeListenerSupport statusChangeListenerSupport = new StatusChangeListenerSupport();
SocketAddress remoteAddress;
DatagramSocket socket;
protected int status = STAT_NOT_LOGED_ON;

protected void receive(byte[] buff) throws IOException {
DatagramPacket packet = new DatagramPacket(buff, buff.length);
do {
socket.receive(packet);
} while (packet.getSocketAddress().equals(remoteAddress));
}

protected void send(byte[] buff) throws IOException {
DatagramPacket packet = new DatagramPacket(buff, buff.length);
packet.setSocketAddress(remoteAddress);
socket.send(packet);
}

public GUET_UDPControllerServer(SocketAddress remoteAddress) {
try {
this.remoteAddress = remoteAddress;
socket = new DatagramSocket(CLIENT_LISTEN_PORT);
} catch (SocketException ex) {
Logger.getLogger(GUET_UDPControllerServer.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}

public void logon(Account account) throws AccountException {
try {
setStatus(STAT_LOGON_PENDDING);
GUET_PreLogonPacket lp = new GUET_PreLogonPacket(account.getName());
send(lp.toByteArray());
byte[] buff = new byte[22];
receive(buff);
lp.readByteArray(buff);
switch (lp.status) {
case GUET_PreLogonPacket.STATUS_ERROR:
throw new AccountNotFoundException();
case GUET_PreLogonPacket.STATUS_LOCKED:
throw new AccountLockedException();
case GUET_PreLogonPacket.STATUS_OK:
break;
default:
throw new IOException("Illegal PLP.status");
}
lp = new GUET_LogonPacket(account.getName(), account.getPassword());
send(lp.toByteArray());
buff = new byte[32];
receive(buff);
lp.readByteArray(buff);
switch (lp.status) {
case GUET_PreLogonPacket.STATUS_ERROR:
throw new AccountNotFoundException();
case GUET_PreLogonPacket.STATUS_LOCKED:
throw new AccountLockedException();
case GUET_PreLogonPacket.STATUS_OK:
break;
default:
throw new IOException("Illegal PLP.status");
}
setStatus(STAT_LOGED_ON);
} catch (IOException ex) {
Logger.getLogger(GUET_UDPControllerServer.class.getName()).log(Level.SEVERE, null, ex);
throw new AccountException("Error while commucating with server: " + ex);
}
}

public void logoff() {
if (getStatus() != STAT_LOGED_ON) {
throw new IllegalStateException("not loged on!");
}

}

public int getStatus() {
return status;
}

protected void setStatus(int status) {
int oldstst = this.status;
this.status = status;
statusChangeListenerSupport.fireStatusChanged(oldstst, status);
}

public void addStatusChangeListerer(ServerStatusChangeListerer linstener) {
throw new UnsupportedOperationException("Not supported yet.");
}

public void removeStatusChangeLinstener(ServerStatusChangeListerer lintener) {
throw new UnsupportedOperationException("Not supported yet.");
}

public Collection getStatusChangeListeners() {
throw new UnsupportedOperationException("Not supported yet.");
}
}

某熊又回来了

历经千辛万苦,爬过雪山,做过沼泽,进行N次空间跳跃,更换了无数次BSP,最后某熊作出了一个伟大的决定:我还是回来吧……NND全世界BSP千千万,就是没有一个适合某熊的……我先去面个壁去……

2008年6月23日星期一

[转]控制台下的输出色彩控制

VT100控制符文档
这个东西很好玩,你可以用这些东西来展现多彩世界。
我在PHP、C/CPP、SHELL等输出文本中都写这些东西。。。

格式:
echo "\033[字背景颜色;字体颜色m字符串\033[0m"

例如:
C程序语句:

printf(" \033[41;36m something here \033[0m");

PHP:

echo "Rpc Time:\033[40;33m",$string,"\033[0m\n";

and so on...
其中41的位置代表底色, 36的位置是代表字的颜色

那些ascii code 是对颜色调用的始末.
\033[ ; m …… \033[0m

字背景颜色范围:40----49
40:黑
41:深红
42:绿
43:黄色
44:蓝色
45:紫色
46:深绿
47:白色

字颜色:30-----------39
30:黑
31:红
32:绿
33:黄
34:蓝色
35:紫色
36:深绿
37:白色

==============================ANSI控制码的说明
\33[0m 关闭所有属性
\33[1m 设置高亮度
\33[4m 下划线
\33[5m 闪烁
\33[7m 反显
\33[8m 消隐
\33[30m -- \33[37m 设置前景色
\33[40m -- \33[47m 设置背景色
\33[nA 光标上移n行
\33[nB 光标下移n行
\33[nC 光标右移n行
\33[nD 光标左移n行
\33[y;xH设置光标位置
\33[2J 清屏
\33[K 清除从光标到行尾的内容
\33[s 保存光标位置
\33[u 恢复光标位置
\33[?25l 隐藏光标
\33[?25h 显示光标

2008年6月18日星期三

答辩?还是便秘?

==本文纯属吐槽,请无视,谢谢==
今天参加一个C语言实训的答辩,气死某熊了。吐槽一下,以解心头之气。

本来是C语言的实训,有人竟然堂而皇之地用C++,还用MFC,而且所有人都是讲的很长很长很长很长很长很长很长很长很长很长,而且,我排在最后一个,从7:30等到9:00还没结束。

然后是内容,不是什么***管理系统,就是***销售系统。烦都烦死了。总之感觉就和小孩过家家一样没意思。

等到我的笔记本剩余电量小于20%之后,某熊彻底丧失耐心,走人。去TNND的大便吧……

2008年6月17日星期二

IcyBear's File Storge Server

其实并不是一个服务器软件……因为那个空间不支持目录浏览,而且还有关不掉的防盗链功能……极其郁闷……所以就写了这个玩意儿……好久没碰ASP了,都忘了怎么写了,一开始每句后面习惯性加一个分号if语句总是不自觉的加上大括号啥的……

链接在这里:
这是代码
这是示例

2008年6月15日星期日

某熊犯难……到底是用哪边比较好?

现在犯难中……是应该继续用原来的WordPress呢?还是换到Blogger呢……MS两边都不是特别稳定……

2008年6月14日星期六

此博客调整中

此博客目前正在调整中……
由于某喜欢水产的SB ZF的某SB GFW,目前某熊正在抓狂ing.....
原来的WordPress现在在http://wp.icybear.cn

2008年6月10日星期二

天空中飞舞的妖精——战斗妖精雪风通关留念

前两天下载了一个雪风,用了一个周末的时间把它打通关了……感觉这个游戏可以吐槽的地方不少。

首先,说说剧情,剧情基本上和OVA是一样的,但是只有OVA中的前一两集。整个任务流程非常短。也没有什么分支剧情,任务提示也不是很全……倒数第二关时,他设定的是主角的飞机一定会被击落……但是我左闪又避没有被击落……直接熬到了时间结束,任务失败……这设定也太烂了吧。

然后是3D模型,好吧,作为一个比较古老的游戏,画面基本上还说的过去,但是感觉不如ACE COMBAT系列来的精致,最要命的是飞机的起落架……在跑道滑行时,起落架上的轮子是不会转的……而且飞行时起落架竟然没有收起来……这是何等的师太!

之后是系统兼容性……作为古老的游戏……在新系统上有点问题是正常的,但是这问题的诡异程度就有点麻烦了……但你从游戏里直接切换回去时,你会惊奇的发现……系统就这么卡住了……虽然背景音还在放,但是什么按键都无用了……用Ctrl_Alt_Delete调出任务管理器,发现竟然没法结束进程。因为鼠标和键盘的输入都被游戏拦截掉了……我费了好大的劲才把他结束掉。

最后是按键问题:游戏里只有输入选择是用键盘游戏还是用飞行摇杆,但是没有重新定义键位的选项,幸好本熊是用Jok2Key模拟键盘玩的,感觉用键盘飞模拟飞行类游戏很不爽。

总之,这个游戏的评价并不很高,我也是冲着雪风的名气才会去下载这个游戏的。

另附:A9VG上的介绍+攻略:

http://bbs.a9vg.com/read.php?tid=460154&fpage=1&toread=&page=1

以上。