總網頁瀏覽量

2013年2月27日 星期三

多型plymorphism

簡單來說:在繼承關係之下,透過父類別的類別變數執行子類別的method。

定義:在執行程式,物件能夠依照不同情況變換資料型態。換句話說,多型是指一個類別參考可以在不同環境下,扮演不同角色的特性,指向不同的物件實體,可透過實作多個繼承或介面來實現父類別,並使用Override或Overload來達成。

物件在執行時會依據指向的物件實體類型來呼叫對應方法。前提:子類別必須改寫(override)父類別的方法。
JVM在執行階段可以確認每個物件的實際類型,並呼叫對應方法。
使用多型是為了避免轉型。

作法:
用父類別宣告一個類別變數
這個類別變數用子類別來(new)建立物件


結論,構成多型的三要素,缺一不可:
1.類別要有繼承
2.類別要改寫父類別的方法
3.父類別調用指向子類別的物件


對於java來說,應該呼叫哪一個方法來執行,與變數本身所屬類別無關,而是跟物件本身所屬類別有關。


2013年2月26日 星期二

super用法

super:執行程式時一個物件,指向該物件的父類別。

一、子類別在建構子中初始化時用super();呼叫父類別建構子初始化

例如:
class Human{
public Human(){
System.out.println("Hahaha");
}

public void say(){
    System.out.println("Catch a murderer");
}

}

class Detective extends Human{//繼承Human
public Detective(){
super();
/*
super指向Human物件,在這裡用super呼叫Human建構子。
這邊不寫super,系統會默默地在第一行自動補上super。所以在建立subclass物件時會呼叫superclass建構子做初始化。super必須寫在建構子的第一行,如果不寫在第一行,那麼編譯階段,物件初始化時系統會自動在建構子第一行補上super()做初始化,之後又碰上開發者自己加入的super()又一次初始化就會產生error。
*/
}

@override
public void say(){
System.out.println("Yout are the murderer");

}

public void catchmurderer(){
    super.say();
}

   
}

public class mypractice {
    public static void main(String[] args) {
    Detective conan = new Detective();  
    conan.catchmurderder();
    }
}



子類別建立物件會先呼叫父類別的建構子初始化
由上面例子Detective建立conan物件時會呼叫Human類別的建構子做初始。
其實這樣設計也符合邏輯
子類別繼承自父類別的成員函數與成員變數
兒子擁有老爸一些特徵,這些特徵在老爸出生時就決定了。
兒子出生時老爸的特徵一定先出現。


在java世界裡所有的類別都是繼承自Object這個類別
因此所有的類別宣告建構子時候,系統都會默默地補上super();
去呼叫Object的建構子做初始化。

本篇例子:Detective建立物件時會(Detictive→Human→Object)層層遞迴呼叫父類別建構子做初始化。先在Object建構子初始化,接著在Human建構子初始化,最後是在Detective初始化。



二、子類別改寫(override)父類別的method或variable後,要使用父類別的method或variable時,就用super.method();呼叫父類別的method




2013年2月24日 星期日

在inhon g1手機跑自己開發的程式

作業系統:win7
本篇是設定在Inhon g1手機跑自己用eclipse的程式
首先準備好自己打的程式

一、設定手機
1.系統設定→開發人員選項→將USB偵錯打勾
2.將手機插上電腦

二、設定電腦
1.去android sdk manage安裝use driver
2.下載inhon gi驅動程式 MT65XX好像是聯發科設計的??
MT65xx android phone
(去網路找吧)
3.去裝置管理員安裝驅動程式(youtube 有安裝驅動程式影片教學)
4.想要跑的project點下右鍵→Run as →Run configuration
→左邊選單點下android application→右邊的target頁面選lunch on all compatible devices→在android頁面打上project名稱
5.試著run看看




PS:
檢查電腦有沒有偵測到手機
打開命令提示字元,去sdk目錄底下的platform-tool
打上adb devices
如果螢幕上有出現裝置編號(型號)那麼就安裝成功

也可以打開eclipse:
然後上面一排工具選項點選window→show view→other→新增devices
,畫面下方有devices的資訊,若有手機型號那麼就安裝成功了



linux安裝法:

一、設定手機
1.系統設定→開發人員選項→將USB偵錯打勾
2.將手機插上電腦

二、
在終端機切換到sdk的platfom-tool之下
sudo ./adb kill-server
sudo ./adb start-server
記得要以root權限操作

如此以來在linux安裝就完成

android 更新sdk之後出現please update ADT to the latest version的解決方法

修改sdk\tools\lib\plugin.pro

將版本編號改成更新前的版本編號



2013年2月22日 星期五

ASP連結資料庫

資料哭與ASP.net連線
新增一個資料集,拉TableAdapter(表格配接器)。
1.
TableAdapter:連線到資料庫,針對開發系統需求撈出資料產生資料集。
2.
更改TableAdapter的屬性Name,可以用他的Name在C#作類別變數宣告
3.
我們在C#裡面,用程式將資料顯示在gridview上。
主要架構


在C#程式碼中。
 DrinkDataSet ds;//宣告在page_load之外
在page_load中
  ds = new DrinkDataSet();//建立物件並初始化
  DrinkDataSetTableAdapters.DrinkTableAdapter drink_da = new DrinkDataSetTableAdapters.DrinkTableAdapter();//宣告資料表單配接器,
        drink_da.Fill(ds.Drink);//將資料配接器倒入資料集
        GridView1.DataSource = ds.Drink;//DataSource是物件,指定GridView資料獲取的對象
        GridView1.DataBind();//資料綁定,將table輸出在gridview

//上面兩行相當於GridView1.DataSourceID="NorthwindSqlDataSource"
    }

設定分頁:
1.將gridview的屬性allow paging設定成true
2.這時按下分頁會發生"找不到PageIndexChanging事件"錯誤訊息。(我想是因為按下分頁索引觸發PageIndexChanging事件,而C#找不到相對應的method)因此要在事件表單單的PageIndexChanging點兩下,C#出現PageIndexChanging的method。
3.雖然已經藤上去PageIndexChangeing的method,
但是點下分頁索引時gridview仍不會跳頁,因為我們沒告訴gridview該跳頁了,他頁數索引一直停留在第一頁。
因此
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
    { 
        GridView1.PageIndex = e.NewPageIndex;
//更新GridView的PageIndex(頁數),將換頁事件的頁數給gridview的頁數。      
GridView1.DataBind();//資料綁定,其實不綁定好像也可以秀出頁面,目前好像沒有bug
   
//e是換頁事件,是一個物件,將他轉成字串印出來是System.Web.UI.WebControls.GridViewPageEventArgs
      
    }



由 GridView 'GridView1' 引發但尚未處理的事件 RowCancelingEdit。

2013年2月19日 星期二

Eclipse快捷鍵技巧與密技

"Alt"+"/"
自動補齊函式名稱功能,如果沒有自動補齊那就非常可能前面程式某個地方寫錯或漏寫。

"Ctrl"+"Shift"+"o"
自動import類別功能。

加入程式碼行號
在程式編輯視窗左邊灰色邊框按下滑鼠右鍵→show line numbers


設定多個中斷點執行程式時
按F8可以一步步執行中斷點下方的程式碼

ctrl+/
多行註解

ctrl+h
搜尋


執行插入引數 或給指令
run configuration→arguments
program arguments:是給main method引數
VM arguments:是給JVM的指令 例如:設定系統屬性、classpath





2013年2月18日 星期一

ADO.net(windows form developer)

一、從資料庫撈資料在gridview顯示。
右邊工具箱→資料→右鍵選"選擇項目"→
將sqlCommand、sqlConnection、sqlDataAdapter打勾→
拉sqlConnection,sqlCnnection有個屬性ConnectionString,設定連接到資料庫
(在程式碼打上「sqlConnection物件名稱.Open()」測試有無確實連到Database)→拉sqlDataAdapter設定資料配接器→選擇sqlConnection所連接的DB(這邊若選擇跟sqlConnection不一樣的DB,系統會自動建立新的sqlConnection)→選擇SQL模式→選擇資料表單、欄位→完成之後"產生資料集"→按下確定產生DataSet元件,其中DataSetName改成有意義易懂的名稱
→拉bindingsource,屬性datasource選擇"執行個體"的dataset(執行個體就是物件;"專案資料來源"是類別);之後屬性datamember選擇資料表單→拉datagridview,屬性datasource選擇bindingsource→拉一個button,點兩下,在click事件中打上「資料配接器物件的名稱.Fill(dataset物件的名稱)」

執行程式按下button後gridview會顯示select之後的datatable才算成功。


資料庫:可以是MSSQL
dataAdapter:藉由sqlconnection與資料庫連線。對資料庫下SQL指令。透過.Fill()可以將指令執行結果丟給dateset物件。
Dataset:存放資料表單,資料表單也稱為datamember。收到.Fill的指令之後,Dataset與資料庫斷線。因此dataset可以讓開發者在離線狀態操作資料庫。
bindingsource:gridview與dataset連接橋梁。
datagridview:顯示資料表單



選擇項目:讓工具箱擁有更多控制元件

sqlConnection元件的屬性ConnectionString:
Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True
Data Source:指定server名稱,也可替換成Server
Initial Catalog:指定database名稱,也可替換成Database
Integraged Security:true表示用windows驗證模式連線,用windows登入帳密去連資料庫;如果為false則為sql模式驗證,必須加上帳號與密碼。


每個元件的屬性(Name):物件的名稱,在.cs檔案C#的程式之中用此名稱呼叫物件。


二、產生xml碼

拉出一個bottun→在click事件打上
DataSet名稱.WriteXml(@"D:\write.xml",XmlWriteMode.DiffGram);

@"D:\write.xml"是路徑以及文件名稱
XmlWriteMode.DiffGram是輸出格式

如此一來可以配合上一大段,在撈出資料後可以產生一個xml檔案



三、

2013年2月17日 星期日

activity_lifecycle( I)

activity:在智慧型手機打開應用程式(google map、email、看圖程式)之後,每個視窗都是activity。一個應用程式(Application)可以有多個activity
每個應用程式都有MainActivity相當於C語言的主函式。
每當開啟新的activity(開新視窗)那麼之前的activity進入stop狀態
但是並非終止(kill)而是將activity存放在系統記憶體堆疊之中


Create Activity:

每個開發者寫的activity必須繼承Activity這個類別(extend Activity)。
在這個activity(不知道只有MainAcitvity還是所有的activity)
必須實作(callback methods)
當activity發生create(新開視窗)、stop(跳到其他視窗)、
rsume(跳回原本視窗)、destroyed(關閉視窗,)會呼叫這些callback methods

其中兩個最重要的callback methods是:
onCreate():
activity之中必須有這個method.每當開啟activity一定會先呼叫這個funcction
最重要的是必須呼叫setContentView()顯示使用介面的版面配置

onPause():
使用者離開activity時候會呼叫這個function;離開不代表關閉activity,有可能只是暫時停用。

Implement user interface(實作介面):
android看到的按鈕、文字框框、選項框框等這些東西,在android視為"物件"又稱作Widgets(小裝飾品),這些物件由View這個類別衍伸而來。
我們可以用這些物件來設計視窗的版面,這種動作有個術語稱作
layout(布局、版面配置)。
layout也是物件,也是容器。可以裝其他的layout或者Widgets
layout由ViewGroup衍伸而來(ViewGroup是View的子類別),

除了在xml檔案建立view物件,我們也可以在.java檔案插入view物件







activity lifecycle觀念是很"重要"的"基本"觀念

Android使用Activity的觀念,將執行中的應用程式分成五大類
1.foreground process
2.visible process
3.background process
4.empty process
5.service process


android會依照這五類別判斷執行中的應用程式activity是屬於哪一類型,給予不同生命週期。意味著在android系統中即使使用者沒有將程式關閉,當程式處於某種process類別時,有可能自動被android給關掉(kill)。

因此程式存在與否並非由應用程式本身自行決定,而是由android透過運行機制,依照那些畫面或訊息對使用者最重要或系統目前有多少記憶體可用,來決定是否關掉程式。





底下的protected都是用overriding技巧


package com.example.liearlayouttest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView red;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        red =(TextView)findViewById(R.id.red);
       
        red.setOnClickListener(new OnClickListener(){
       
            public void onClick(View arg0){
                toPage2();
               
            }
       
        });
       
        red.setText(" "+red.getWidth());
    }
    private void toPage2(){
       
        Intent it = new Intent();
        it.setClass(this,Page2.class);
        startActivity(it);
       
       
    }
   
    protected void onStart(){
        super.onStart();
       
        red.setText(""+red.getWidth());
    }

    protected void onResume(){
       
        super.onResume();
       
        red.setText(" "+red.getWidth());
       
       
    }
    protected void onPause(){
        super.onPause();
       
        Log.i("yyp",""+red.getWidth());
    }

    protected void onStop(){
        super.onStop();
       
       
        Log.i("yyp",""+red.getWidth());
       
    }
   
    protected void onRestart(){
       
        super.onRestart();
        Log.i("yyp",""+red.getWidth());
 //紀錄執行的過程並顯示出來      
       
       
    }
   
   
}

LinearLayout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
版面配置標籤

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:orientation="vertical" >
元件擺放的順序,
vertical:元件由上而下擺放
horizontal:元件由左而右擺放
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
這裡的match_parent意思是依照第一個LinearLayout容器設定元件大小

        android:layout_weight="1"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/red"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
這裡的TextView是依照上面第二個LinearLayout容器設定元件大小
            android:layout_weight="1"
            android:background="#ff0000"
            android:text="red" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#00ff00"
            android:text="yellow" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#0000ff"
            android:text="blue" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#ffff00"
            android:text="green" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center_vertical|center_horizontal"
            android:text="row1" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="row2" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="row3" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="row4"
            android:textColor="#0ff000"
            android:textSize="32sp" />
    </LinearLayout>

</LinearLayout>

relativelayout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <RelativeLayout
 android:id="@+id/top"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
 android:layout_alignParentTop="true"
(相對位置擺在父容器裏頭的頂端)
        >
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="Guess"
        />
   
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@+id/btn"
//告訴edittext位於Button的左手邊
         android:layout_alignTop="@id/guess"
     android:layout_alignBottom="@id/guess"
(向guess分別頂端對齊、底部對齊,讓版面看起來更工整)
      />
</RelativeLayout>
<LinearLayout
 android:id="@+id/bottom"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_alignParentBottom="true"
  >
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
(讓button的大小平均分配在LinearLayout。如果父親容器是RelativeLayout,則不能用此屬性)
    android:text="newgame"
android:background="#AFD1E3"
    />
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
android:layout_weight="1"
    android:text="setting"
android:background="#AFD1E3"
    />

    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
android:layout_weight="1"   
android:text="help"
android:background="#AFD1E3"
(設定按鈕顏色:可以去color picker抓顏色的編碼)
    />
  </LinearLayout> 
<TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#D1957D"
        android:layout_above="@id/bottom"
(指定TextView相對位置)
        android:layout_below="@id/top"
  (指定TextView相對位置)
若沒寫上面這兩行TextView就會填充整個螢幕


/>
 

</RelativeLayout>



2013年2月6日 星期三

android第一篇code review


本android在windows環境開發

adb.exe放在
sdk\platform-tools之下

android模擬器開超慢,看起來沒有好的解決方法
不過比第一台筆電好多了


重要檔案
R.java:類別資源索引檔,位於gen(generated)底下,
activity_main.xml:位於res(resources)/layout底下
MainActivity.java:位於src底下
AndroidManifest.xml:應用程式定義檔,每個APK應用程式的根目錄必須有這個檔案。這個文件定義出應用程式的整體布局,包含該應用程式提供的activity、服務、處理的數據、軟體版本、軟體名稱、UI屬性設定、。
我們點選這檔案可以在exporting這段底下有個連結
"Use the Export Wizard to export and sign an APK"或者"
Export an unsigned APK ",就可以將APK匯出到個人電腦上,不用透過eclipse將APK檔案裝在android模擬器上再用adb pull下載。



android SDK提供的API放在lib資料夾底下jar檔案。

第一行
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns是xml namespace的縮寫,每一個android XML設計檔案UI設定必須以此宣告開始,xml檔案底下所有的android變數將代表http://schemas.android.com/apk/res/android
藉此連結引用android系統提供的使用者介面資源,這個是UI設計的固定用法。




Android程式運作原理:
android編譯java原始碼交給一個名字叫做ANT的工具來做,然後呼叫javac編譯程式,Ant採用XML來撰寫編譯行程。

當 我們編譯程式碼,java不會編譯成ByteCode而是被Ant編譯成Dalvik Bytecode(*.dex),然後再和其他資源檔打包成APK套件,最後在Runtime時候,透過Android Code Libraries這個很大的Java類別總集JAR(Java ARchive)檔案與上層的java程式溝通,而Dalvik虛擬機器則解讀dex檔案,與下層使用C語言寫成的Linux Library函式庫溝通,然後由底層的Linux Kernel產生一個行程(process)執行該程式,這就是完整的Android程式運作原理。


dx 是一套工具,可以將 Java .class 轉換成 .dex 格式. 一個dex檔通常會有多個.class。由於dex有時必須進行最佳化,會使檔案大小增加1-4倍,以ODEX結尾



編譯之後會.apk檔案會出現在
C:\Users\YYP\workspace\guessnumber\bin




TextView皆是個View。是View的類別
  注意大小寫

<RelativeLayout xmlns:yyp="http://schemas.android.com/apk/res/android"
    yyp:layout_width="match_parent"(match_parent表示寬度大小要match父類別)
    yyp:layout_height="match_parent">
  
    <TextView
        yyp:id="@+id/textbox1"//打完這行,gen底下的R.java的id 會自動加上textbox1記憶體相對應的位置。
@的意思是去R.java檔案,+id/textbox1找到id method並加上textbox1項目,R.java裡面紀錄View的記憶體位置。

        yyp:layout_width="wrap_content"//寬度要占據多大 fill parent 與 match parent一樣
        yyp:layout_height="wrap_content"
        yyp:layout_centerHorizontal="true"  水平線至中
        yyp:layout_centerVertical="true"  垂直線至中
        yyp:text="@string/hello_world" (@string表示將字串定義在res\values\strings.xml這個檔案,而hello_world表示儲存字串的變數的名稱。
我們可以在strings.xml裡面看到如下這一行
string name="hello_world">Hello world!</string>
因此在demo程式時,畫面會顯示Hello world而非hello_world
)
/>

</RelativeLayout>


在MainActivity.java檔案裡

import android.app.Activity;
import android.view.Menu;
這兩個類別分別是android系統架構圖片中Application Framwork裡面的Activity Manager以及View System

Activity Manager在模擬器上產生視窗事件
View System在此視窗上顯示TextView的內容

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

在MainActivity.java檔案裏頭,使用onCreate()來啟動activity事件
並且使用saveInstanceState儲存此activity的目前狀態
透過setContentView呼叫R.java資源索引檔裏頭的layout布局類別裡的activity_main,也就是在螢幕上顯示activity_main.xml布局
(setContentView 也可說是xml與mainactivity的橋樑,先在MainActivity.java裡面指定要針對哪個layout.xml寫程式,先找到 layout在針對layout裡面元件(ex:Button,TextView)寫程式。)



這裡的onCreate方法是override父類別Activity的onCreate方法 ,
在super.onCreate(savedInstanceState);呼叫父類onCreate別方法,
確保父類別所作的初始化,會在MainActivity.java的onCreate方法中執行


其中Bundle savedInstanceState,這個參數是用來保存 Activity之前的狀態






import android.widget.TextView;

    TextView yyptext = (TextView)findViewById(R.id.tv);
//findViewById是View型態。因為R.java裡面紀錄的是View的記憶體位置,findViewById會找到TextView的記憶體位置,回傳View物件,TextView是View的子類別,所以要將xml裡面的TextView給main.java裡面的yyptext使用時,必須作型別轉換,將View轉換為TextView


 guess.setOnClickListener(new OnClickListener() {
        public void onClick(View arg0) {
        doGuessProcess();
        }        }); }

這裡寫法有兩個術語來說:callback與listener

android是屬於互動式應用程式 ,有些method無法讓我們主動呼叫
而是透過使用者的動作(ex:按下按鈕)。才會由系統呼叫這些方法。
這種類型的方法稱之為callback方法。
上面的public void onClick是callback方法。

android要怎樣知道使用者已經有所動作(ex:按下按鈕)?,
android有傾聽者(Listener) 機制,去偵測使用者跟系統互動。
 上面的setOnClickListener就是傾聽者,裡面包了一個callback方法--onClick,
透過new OnClickListener()傾聽者物件操作onClick。


setOnClickListener 是 View 類別所提供的方法,因為 Button 類別是繼承自 View 類別,
guess是Button 類別的物件實體,因此能夠呼叫 setOnClickListener 方法。

doGuessProcess()必須放在 onClick裡面,



 yyptext.setText("I want to play a game");
在View顯示文字I want to play a game.
View的名字. setText(字串或字串變數或空字串); 
例如:msg.setText(++counter+"."+numtextbox.getText().toString()+":"+result+"\n");
也可以用附加方式顯示文字
View的名字.append(字串變數或字串);
例如:msg.append(++counter+"."+numtextbox.getText().toString()+":"+result+"\n");
再一次呼叫append,文字會附加在已顯示文字的後面
已顯示的字串不會被清掉,會在buffer中

判斷字串,相同與否
result.equals(nowdig+"A0B")
若字串變數result與nowdig+A0B相同會回傳true。


從xml的view擷取字串的方法.getText(),不過一律要加上.toString()
String gnumber = numtextbox.getText().toString();


擷取gnumber字串中第i個字元,取出的字是字元型態非字串型態
gnumber.charAt(i)==answer.charAt(i))


搜尋字串
answer.indexOf(gnumber.charAt(i)+"") 
回傳整數,gnumber第i個字元位於answer的第X個字,如果沒有,indexOf會回傳-1。因為回傳0表示gnumber的某個字元與answer的第一個字相同。


整數轉成字串
Integer.toString(數字或整數型態的變數);


判斷字串A是否包含字串B
A.contains(字串序列B或單一字串)
回傳boolean值


安裝下載的app
./adb install XXX.apk(這是linux語法)




2013年2月5日 星期二

安裝Oracle11 R2 in windows server 2008

安裝環境:
virtual box的windows server 2008安裝oracle11g

去官方網站下載第十一版
官網將檔案分兩個壓縮檔
下載之後務必將第二個壓縮檔放進第一壓縮檔
對應的資料夾

開始安裝:

第一步驟:
要不要給email獲得官網資訊安全更新資料
通常跟垃圾信件差不多
且不想讓他占據資源,我取消打勾。

之後出現
do you wish to remain uniformed of critical security issues in your configuration?

將yes打勾吧!!!


第二步驟:
因為是第一次裝DB就選第一項
create and configuration database
建立並規畫資料庫


第三步驟:system class
desktop class 是輕量(minimal)安裝
server class 當作資料中心用的,電腦當server用的就選這個


第四步驟:grid installation options
因為資料庫只裝在一台電腦
選single instance database installation
(另一個是cluster database用的)


第五步驟:install type(安裝種類)

之後想設定system密碼、字元集、DB語言,選 advance。
選typical type(典型安裝)以上都會採用預設值


第六步驟:如果電腦時區設定是台北,語言就選traditional chinese
第七步驟:instal location
oracle安裝路徑採預設值

第八步驟:configuration type
選一般用途與交易處理
(選資料倉儲用途是要OLAP跟data mining)

第九步驟:database indentifiers
設定全域資料庫名稱
與service identifier(SID)
在global database name打上first

在SID說明他的意思是好像是
"一個資料庫由一個以上oracle instance認領,資料庫要辨認是哪個oracle就是藉由SID"

全域資料庫名稱:配合domainName取資料庫名稱
DomainName名稱不一定要跟DNS網域名稱一樣
全域資料庫名稱在網際網路是獨一無二的。



第十步驟:configuration options
memory設定350    (隨安裝者高興,不要太低ex:給10MB)
字元集選 utf8  (國際通用的)
security:將assert all new security setting打勾
sample schema:第一次建立DB,將建立sample schema打勾
往後建立第二個DB時候可以套用此sample schema


第十一步驟:management options
採用data control

第十二步驟:database storage
資料庫、資料表單存放路徑,採預設值

第十三步驟:backup and recovery
目前還不熟oracle
選不要自動備份還原

第十四步驟:schema passwords
設定sys,system,sysman,dbsmp密碼
sys權限比system高

第二個選項是懶人設定法
將四個帳號密碼設定一模一樣
切記密碼不要有@ /

第十五步驟:prerequiste checks 必要查核
這邊告訴你目前環境設定。


安裝過程依然到45%就慢下來,
這時系統正在創造log file存放路徑






全域資料庫名稱:配合domainName取資料庫名稱
DomainName名稱不一定要跟DNS網域名稱一樣
全域資料庫名稱在網際網路是獨一無二的。



最後出現enterprise manager configuration fiail
監視器程序未啟動或資料庫未註冊到監視程序
啟動監視器並註冊資料庫服務,之後重新啟動EN Configuration Assistant
有關資料請參考D:\Oracle\cfigtoologs\dbca\first\enConfig.log 中的日志文件。
之後可以手動 D:\Oracleproduct\11.2.0\dbhome_1\bin\emca脚本,重新使用Enterprise Management

網路說大可不必重裝

目前初步排除密碼的問題
排除時差的問題


去cfigtoologs\emca\first
查log檔案
出現多次socket read timeout
(初步判斷可能是IP設定有問題)




找到解答是說:
只要將OracleOraDb11g_home1TNSLitener、OracleRemExecService和OracleServiceORCL
這三個service precess 啟動即可

不過我無法啟動OracleRemExecService
因為service表單裡面找不到


enterprise manager configuration assistant(emca)
在cmd打下面指令重新設定
組態變數
emca -config dbcontrol db -repos recreate
仍然無法安裝成功em

監聽器port要設1521
如果設定1158系統不給過
會找不到監聽器service




之後在其他網站又查到
Cause: The windows Server 2008 machine is in an active directory and is using IPv6. When the short hostname is pinged, it is resolved via the fully qualified hostname to an IPv6

I was able to fix the issue by following these steps:

Add entries into the host file, to force IPv4 style resolution:-

1) edit the windows\system32\drivers\etc\hosts file

2) add an entry for the machine of the format:-

<ipaddress> <fully qualified hostname> <short hostname>

Document ID: Error Uploading Configuration Data To The Repository" when configuring dbconsole [ID 1233913.1]


另一位是說:

I have checked the hosts file under system32/drivers/etc. There is no setting in it.
So I changed the configure in it with below:
127.0.0.1 localhost
172.16.1.37 windows-a
And I try to create the EM setting again.

It works.
So for windows 2008, you need to do two things:
1. configure the hosts file;
2. close the firewall;
Thank you so much for your help.


另一個網站說:

windows server 默認使用IPV6協議解析,在命令提式字元ping電腦主機,他通過完整主機名稱解析到IPV6地址

ping localhost 
結果秀出
IPV6格式的 "  ::1: "
 
DBconsole 11.2圍繞網格控制(grid control)10.2.0.4,所以不支持IPv6兼容。
網格控制11.1.0.1是IPv6兼容。

也就是說操作系統使用IPV6解析地址,而EM需要IPV4解析地址。
解決方法:強行使用IPV4解析地址

1.編輯windows\system32\drivers\etc\hosts.file
2.添加一個ip 與 主機名稱解析的格式

<ipaddress> <fully qualified hostname> <short hostname> <ip地址><完整主機名稱> <短主機名稱>

eg.例如。

192.168.77.1 swspor.oraclemachine.com oraclemachine

127.0.0.1  localhost
10.0.2.2    first



再去cmd
ping localhost
變成IPv4解析了


之後手動建立em


更改host.file終於成功建立emca
可以打開
http://localhost:1158/em
但是是空白的網頁

且service看不到OracleRemExecService



空白網頁問題
有人說是環境變數路徑衝到

新建path为SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem
不行就重新安装IIS系统组件



有人說是安全性的問題
http://localhost:1158/em加入到信任網站



事實上就是安全性的問題。
之後可以開啟網頁
並且在service 找到oracleremexecservice以及oracledbconsoleOOXX


心得:
這問題卡了三天才解決。
重裝了四五次左右。
很多事情就是江湖一點訣
需要靠經驗才能處理

網路上爬文看了許多論壇
發現很多人習慣跟發問者講模模糊糊的題示(大多數有講跟沒講一樣)。
乍看之下是讓網友有學習機會
但這只是讓人重新發明輪子(Reinventing the Wheel)而已
花很多時間在解決別人很久以前就解決的問題
其實只要知道輪子怎樣做出來就夠了



圖形介面管理工具網址:
https://first:1158/em/console/logon/logon

2013年2月4日 星期一

cursor Lab


cursor(資料指標)
cursor本質上算是table一種。
能夠逐筆取出資料單獨處理,這是select辦不到的事情。


主要用於SQL批次、預存程序、自訂函數、觸發程序中
常常與迴圈(while)配合



use Northwind
GO

1. 定義 Cursor (請留意 Keyset 選項)
DECLARE CursorLab CURSOR
Keyset//若沒打這行則預設為Dynamic,則cursor內容會隨時動態更新
FOR
select * from Customers
  order by CustomerID


Keyset:只將select出的資料中,具有唯一性的鍵值欄存入"暫時資料表"中(這個暫時資料表名稱為Keyset),其他欄位則動態由原始資料讀取。當原始資料被更改時,若未更改到健值欄,則可透過cursor讀取到最新資料;但是若鍵值欄被更改或紀錄被刪除了,那麼經由cursor去讀取該筆記錄時,即會發生@@FETCH_STATUS為-2的錯誤(但若該項更改或刪除是經由cursor去進行的,則仍可正常讀取不會有誤)。

2.開啟 Cursor
OPEN CursorLab

3.請檢視第一筆的內容
FETCH NEXT FROM CursorLab

只秀出一筆資料
ContactName欄位值為Maria Anders

4.在另一個新增查詢視窗(第二視窗) 修改資料
update Customers set ContactName = 'Maria Anders2' where CustomerID = 'ALFKI'

原始資料被更改,未更改到健值欄


5.在第一視窗返回前一筆(原先的第一筆), 資料內容是什麼?
FETCH PRIOR FROM CursorLab

可透過cursor讀取到最新資料
欄位值改成了Maria Ander2

6.關閉  刪除cursor
CLOSE CursorLab
deallocate CursorLab


---------------cursor 在while loop的應用-----------------

use Northwind
go

declare LabCursor cursor keyset for
  select ProductID, ProductName, UnitsInStock
    from Products
    order by ProductID
   
open LabCursor

print @@FETCH_STATUS//此時值為-1

fetch next from LabCursor//所以進行while前要fetch next一次

while @@FETCH_STATUS = 0
begin
  fetch next from LabCursor
end
print @@fetch_status//while完整跑完時,fetch status為-1
close LabCursor
deallocate LabCursor

-------------cursor抓取的資料丟給變數--------
declare LabCursor cursor keyset for
  select ProductID, ProductName, UnitsInStock
    from Products
    order by ProductID
declare @ProductID int
declare @ProductName nvarchar(40)
declare @UnitsInStock int
open LabCursor
fetch next from LabCursor into @ProductID, @ProductName, @UnitsInStock

while @@FETCH_STATUS = 0
begin
  fetch next from LabCursor into @ProductID, @ProductName, @UnitsInStock
將fetch抓出的紀錄,丟給變數
print @Productid
print @productname
print @unitsinstock
end
close LabCursor
deallocate LabCursor


---利用cursor將資料丟到暫存table,-----------------------

use Northwind
go
create table #Report
(
  ProductID int,
  ProductName nvarchar(40),
  UnitsInStock int,
  cUnitsInStock int
)
go
declare LabCursor cursor keyset for
  select ProductID, ProductName, UnitsInStock
    from Products
    order by ProductID
declare @ProductID int
declare @ProductName nvarchar(40)
declare @UnitsInStock int
declare @cUnitsInStock int = 0
open LabCursor
fetch next from LabCursor into @ProductID, @ProductName, @UnitsInStock
while @@FETCH_STATUS = 0
begin
  set @cUnitsInStock = @cUnitsInStock + @UnitsInStock//算商品總庫存量
  insert into #Report values
    (@ProductID, @ProductName, @UnitsInStock, @cUnitsInStock)
  fetch next from LabCursor into @ProductID, @ProductName, @UnitsInStock
end
select * from #Report
close LabCursor
deallocate LabCursor
drop table #Report

Transaction--rollback與isolation等級實作

1. 啟動 SQL Server Management Studio, 登入 SQL Server,
   新增查詢, 執行下列指令:
print @@SPID
得到連線id 55

2.去"活動監視器"

3.接著回到查詢部分,下以下指令
begin transaction
select * from Customers
  where CompanyName Like 'B%'
print 'trans count: ' + Convert(varchar(4), @@TranCount)//印出目前有幾筆交易,因為SQL沒有自動轉字串功能所以要將int的TranCount轉成字串。

4.結束交易
commit transaction
print 'trans count: ' + Convert(varchar(4), @@TranCount)

(PS:如果commit transaction前面有指令錯誤的話,SQL會強制取消交易,這時再印TranCount會是零)
(PS:如果有多筆交易,執行一次commit transaction只會結束掉一筆交易)


到這裡可以知道所謂的交易就是由begin transaction .....commit transaction包住的指令。而且還沒下達commit transaction指令,表示transaction尚未結束。

體驗交易處理的完整性與可回復性

5.

begin transaction
update Customers
  set CompanyName = 'Bottom-Dollar Markets 123'
  where CustomerID = 'BOTTM'//update 資料

select * from Customers
  where CompanyName Like 'B%'

此時發現 BOTTM的CompanyName的值已經變成Bottom-Dollar Markets 123


6.接著打上
rollback transaction
//這是取消交易的指令,並且回復到交易前的狀態

select * from Customers
  where CompanyName Like 'B%'
此時,BOTTM的CompanyName的值又變回Bottom-Dollar Markets

//切記已經commit的交易就無法再rollback了

Rollback原理:
利用一個暫時交易紀錄檔來回復異動資料,在transaction開始時,SQLserver會將要更改的資料一 鎖定並且進行更改,同時也會建立一個暫時交易紀錄檔,來存放交易中更改資料的過程及內容。
交易一旦被commit時,則會將暫時交易紀錄檔的內容儲存到資料庫的log檔中,使該項交易異動視為已完成。因此無法rollback回去了。除非使用備份還原功能。



體驗交易的隔離性(Isolation):

一、隔離等級為:read commted

1.開兩個查詢視窗

2.在第一個視窗(spid=55)

set transaction isolation level read committed
begin transaction
select * from Customers
  where CompanyName Like 'B%'


3.在第二個視窗(spid=58)

use northwind
update Customers
  set CompanyName = 'Blauer See Delikatessen 123'
  where CustomerID = 'BLAUS'

之後下指令select CompanyName from Customers where CustomerID='BLAUS'
可以知道在第一視窗進行隔離等級為read commited的交易之下
第二視窗仍可以更動資料,資料更新成功



4. 接著去第一視窗執行:
update Customers
  set CompanyName = 'Bottom-Dollar Markets 123'
  where CustomerID = 'BOTTM'

5.之後去第二視窗執行
select CompanyName from Customers where CustomerID='BOTTM'
這時候無法查詢到資料,因為第一視窗仍在交易進行中,將資料給鎖住(lock)。

打開活動監視器看處理序發現spid為55的源頭封鎖者的值為1,表示第一視窗將資料給鎖住。
再看看id為58的欄位,等候類型的值LCK_M_S ,封鎖者的值是55。

6.去第一視窗打上
rollback tran
這時第二視窗已經秀出查詢結果了。


read commited:第一視窗不允許第二視窗讀取(select)第一視窗正在更新(update)且尚未commit的資料,因此該資料後來被更動的機率就比較小(因為第二視窗等第一視窗更動完再去select),且第二視窗不會讀到交易尚未完成的資料,不過讀完資料後,無法得知該資料是否還會有人來更改。第一視窗在交易過程中,第二視窗仍可以更新(update)其他筆資料,因此同一個交易中第一視窗如有兩次以上select,每次select結果可能不盡相同。



二、隔離等級為repeatable read

1.重複以上1~6步驟再做一次, 但是第一視窗隔離等級改用repeatable read,
    ( 差別在於 repeatable read )
set transaction isolation level repeatable read

2.
我們發現在第三步驟時,第二視窗無法更新資料,被鎖定了。

打開活動監視器看處理序發現spid為55的源頭封鎖者的值為1,表示第一視窗將資料給鎖住。
再看看id為58的欄位,等候類型的值LCK_M_X ,封鎖者的值是55。



在交易中,第一視窗讀取(select)到的資料將不允許別人更改或刪除。如此保證第一視窗在交易中每次都可以讀取到相同的內容。但別人(第二視窗仍可以在該資料表insert資料,所以交易過程中如有兩次以上select時候,可能會突然多出一兩筆記錄來。這就是repeatable read的定義。


別忘了最後一步去第一視窗執行
rollback tran

三、隔離等級:Serializable



__________________________________________________________________
再度體會 Transaction 的「隔離性」
  -- SERIALIZABLE 如何預防 "phantom data"

1.第一個視窗執行以下指令:
set transaction isolation level SERIALIZABLE//記得要改isolation level
begin transaction
select * from Customers
  where CompanyName Like 'B%'
請記住where條件


2. 在第二視窗執行以下指令:
update Customers
  set CompanyName = 'Bottom-Dollar Markets 123'
  where CustomerID = 'CHOPS'
select * from Customers
  where CustomerID Like 'C%'
注意:這邊where條件跟第一視窗已經不同,
第二視窗是更新C開頭的某筆資料
並查詢C開頭的紀錄

3.發現這時第一視窗將資料給lock住了
打開活動監視器結果跟read committed一樣
看處理序發現spid為55的源頭封鎖者的值為1,表示第一視窗將資料給鎖住。

再看看id為58的欄位,等候類型的值LCK_M_X ,封鎖者的值是55。


Serializable:第一視窗會將整個資料表鎖定,不允許別人insert,delete,update資料。其他人必須排隊(serial)等第一視窗交易完畢才可以使用這個資料表。因此serializable的並行性最低。

4.記得去第一視窗執行
rollback tran





心得:實做一遍之後對於交易有概念了,光看書根本無法吸收,不夠具體無法想像。

MSSQL雜記

1.
XML資料型態,欄位存放以XML格式寫成的的文件。有點類似將一張網頁放進一個欄位。書上是以存放一張訂單來說明。
好處在於存放資料彈性、擴充性高,也帶有物件導向資料庫的意味。
一個欄位放一張訂單或放一個影音檔案。

2.
Null表示"不知道"的概念,並非零的意思也不是Null字串。

3.
新增資料表時候,日期欄位可以用getdate()函數取得系統的日期時間,
作為新增資料的日期的預設值
create table TableName(
...
FieldName datetime Default getdate(),
...
)

4.
每一個資料表、view、Index都視為物件。
M$SQL management studio左邊的物件總管的清單有.資料夾圖示的是資料庫物件。
其中:
資料圖表(diagram):以圖形表示個資料表的欄位,以及各資料表間的關聯
資料表(table):一堆資料表單,關聯資料表。
檢視(view):檢視表,也是一堆資料表,由其他資料表選取部分欄位而成。view本身是虛擬資料表。

可程式性:
預存程序(Stored Procedured):預先寫好且經過編譯的SQL程式。效率比一行一行執行SQL敘述來的好
資料庫觸發程序(trigger):存放DDL觸發程序(create table ;create database....),可以檢查資料庫所做的更改是否允許,並自訂錯誤訊息。
類型:使用者自訂資料型態。
儲存體:其中全文檢索目錄功能,用來儲存資料表欄位的全文檢索索引,讓使用者方便且有效率搜尋較長的字串欄位資料。
安全性:其中使用者、角色、結構描述,設定資料庫帳號的權限,設定某些帳號可以登入,某些帳號可以看某些資料表,或者針對資料表作更新,也可以設置黑名單。
使用者:每個資料庫都有自己一組使用者物件,表示這些帳號擁有對此DB有存取權限。dbo與guest是每個資料庫預設就會有的使用者。dbo代表該資料庫的擁有者(database owner),通常表是建立資料庫的人。guest權限預設為關閉的,當guest帳戶全線開啟後,所有使用者皆可以由guest帳戶連到資料庫。
開放guest權限好像無法由物件總管那邊用滑鼠操作,只能用指令,如下:
use databaseName
grant connect to guest
如要關閉使用者權限則:
revoke connect from guest


5.





還搞不懂的:
cursor是儲存查詢結果的資料集,其內的資料可供單筆取出處理
table可以用來暫存一組表格型式的資料
cursor跟table這兩種資料型別只能用在城市中宣告變數型別

Mysql資料複寫

複寫:當一個資料庫(master)更動資料,另一個資料庫(slave)也會跟著更動資料,達到兩邊資料同步。

步驟
1. 在 Master 伺服器建立資料複寫的專用帳號。
GRANT REPLICATION SLAVE ON *.* TO repl IDENTIFIED BY '密碼';
讓repl可以針對所有資料,進行複寫
並且設定密碼。

2. 啟用 Master 伺服器的 binary log 功能。為 Master 與 Slave 伺服器設定唯一的伺服器編號。
Master 的 my.ini 設定檔:
[mysqld]
log-bin=mysql-bin    (複寫靠這個運作)
server-id=1  (靠id 識別主機)
Slave 的 my.ini 設定檔:
[mysqld]
server-id=2

3.重新啟動 兩個MySQL 服務。
4. 記錄 Master 伺服器 binary log 的位置序號。
//FLUSH TABLES WITH READ LOCK;

//如果有做資料更新,或者master要做備份,則可以打上上面指令將資料庫lock住,如此一來master不能create  database,其他人也無法更動資料。

SHOW MASTER STATUS;
結果如下:
File             | Position |
-----------------+----------+
mysql-bin.000001 |      106 |

如果slave的資料是由master 複製貼上,則可以跳過5,6點。前面有打上readlock指令務必要Unlock tables;

5. 備份 Master 伺服器的資料庫。
C:\>mysqldump -u root -pPa$$w0rd -P 3306 --all-databases --lock-all-tables > c:\Lab\dbdump.sql
如果上面有執行read lock指令務必記得
UNLOCK TABLES;

6. 將備份檔複製到 Slave 伺服器並且回存到 Slave 伺服器。
source c:\Lab\dbdump.sql

7. 在 Slave 伺服器設定他的master,並啟用資料複寫,例如:
CHANGE MASTER TO
  MASTER_HOST='主機名稱' 或 'IP:port',
  MASTER_USER='repl',//登入master主機的帳號
  MASTER_PASSWORD='密碼',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=106;
START SLAVE;

2013年2月3日 星期日

jQuery之slide window實作

一定要去jquery官網,下載jquery函式庫
然後要用jquery以前一定要先引入jquery函式庫
 <script type="text/javascript" src="jquery.js"></script>

待續

2013年2月2日 星期六

cookie&session

這兩種用來記錄client幹了啥事情,或者紀錄client的資料。

因為HTTP協議是無狀態的(stateless),
也就是伺服器不知道使用者上一次在同一網頁做了什麼事情,
如果沒有cookie或session在購物網站伺服器並不知道"哪位"使用者買了什麼"東西"。

cookie

為了辨別使用者身份而儲存在用戶端(Client Side)上的資料(ex:帳號密碼,通常經過加密)。存在客戶端硬碟裡,除非手動清除,儲存時間是長久的。

伺服器可以設定或讀取Cookies中包含訊息,藉此維護使用者跟伺服器會話中的狀態。 在剛才的購物場景中,當使用者選購了第一項商品,伺服器在向使用者發送網頁的同時,還發送了一段Cookie,記錄著那項商品的訊息。當使用者存取另一個頁面,瀏覽器會把Cookie發送給伺服器,於是伺服器知道他之前選購了什麼。使用者繼續選購飲料,伺服器就在原來那段Cookie里追加新的商品訊息。結帳時,伺服器讀取發送來的Cookie就行了。 Cookie另一個典型的應用是當登入一個網站時,網站往往會請求使用者輸入使用者名和密碼,並且使用者可以勾選「下次自動登入」。如果勾選了,那麼下次存取同一網站時,使用者會發現沒輸入使用者名和密碼就已經登入了。這正是因為前一次登入時,伺服器發送了包含登入憑據(使用者名加密碼的某種加密形式)的Cookie到使用者的硬碟上。第二次登入時,(如果該Cookie尚未到期)瀏覽器會發送該Cookie,伺服器驗證憑據,於是不必輸入使用者名和密碼就讓使用者登入了。


session


將client端的

2013年2月1日 星期五

傳址呼叫vs傳值呼叫

call by address:
呼叫端的引數與被呼叫端method的參數,指向同一個物件

ex:將物件或陣列傳給method,實際上只是傳該物件或陣列的參考給他而已
被呼叫端method裡面更改變數會影響呼叫端變數的值

call by value;
呼叫端的引數與被呼叫端的參數各自擁有自己的值
被呼叫端method裡面更改變數不會影響呼叫端變數的值

Wrap class(包裝類別)

一、what
定義:替基本型態變數量身訂做的method,打包而成的類別。


二、which
基本型態         包裝類別
boolean             Boolean
char                   Character
int                      Integer
short                  Short
long                   Long
byte                   Byte
float                   Float
double                Double


Interger類別長相如下:
class Integer{
.....
public double doubleValue()//將Integer物件的值轉成double基本型態
public int intValue()//將Integer物件的值轉成int基本型態
public Integer(int value)//建構子
public static int parseInt(String s)//將字串轉成int基本型態
.....
}

因為parseInt是static,因此我們可以不宣告物件,直接用Integer類別存取parseInt
int num =Integer.parseInt("字串");
將字串轉成整數型態並指派給num






Boxing:將基本型態包成對應的物件
Integer I = new Integer(1);//將1打包起來裝在I物件


Unboxing:將物件的value取出轉成對應的基本型態
int i = I.intValue(); //將I物件的value取出給i




autoboxing
Integer I =1;//不用new,自動將int 打包成I


autounboxing
int i = I+2;//自動將I轉成int再與2運算
System.out.println(I);//自動將I轉成int再列印

static

在類別內的變數或函式(method)如果加上這個修飾字,就成為所謂的類別變數或類別方法。
主要用意是產生一個"class專屬"的"共用"資料成員或方法
因為static變數是class層級的東西,所以不可以宣告在method裡面
error: illegal start of expression

意思是這個變數跟函式,專屬於類別而非物件。



如果呼叫或存取static變數、函式,也就沒有this參考
又因為宣告static的方法  沒有this參考 所以在static方法中
不能使用non-static成員
以下是static方法存取non-static的錯誤訊息
(sample8.java:25: error: non-static variable num cannot be referenced from a static context)


使用static函式呼叫其他static函式時
會以自己的類別(class)作為呼叫的對象
幻想它會自動冠上<<類別名稱>>.
在這個例子中會對應到test1.more(2, 4, 4, 4)
之所以一樣都是類別下的成員函式還得加上static
是因為在非static的成員函式中呼叫其他成員函式時
會以自己的實體(instance)作為呼叫的對象
幻想它會自動冠上this.
在這個例子中會對應到this.more(2, 4, 4, 4)





static 函式無法存取非 static 成員(也就是 instance 成員) ,
        但是非 static 函式可以存取 static 成員 ,


特徵是不用建立物件來存取他們,
可以透過類別直接存取

呼叫方法:
Classname.methodname();
Classname.viraible;

不加上static的變數與函式都必須透過物件(實體化)才能存取與設定,因此稱為實體變數、實體方法。



當class載入記憶體時,static屬性的變數與方法就跟著載入記憶體並初始化,之後建立物件時不會再另外載入記憶體給予初始化。



應用方面
static int sum;
可以用來計算建立多少物件