<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網(wǎng) 大學(xué)生計算機(jī)學(xué)習(xí)社區(qū)

    CowNew開源團(tuán)隊

    http://www.cownew.com 郵件請聯(lián)系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

    #

    1、從TextEditor繼承,調(diào)用setSourceViewerConfiguration,并傳進(jìn)去一個從SourceViewerConfiguration 繼承的配置類,就可以實現(xiàn)各種代碼editor。
    2、swt盡量使用GridLayout布局(不是java.awt中的GridLayout,而是swt中的)和GridData域。文章:http://coolbear.yculblog.com/post.89429.html

    3、得到文件的編輯器的方法:
    ??? public static IEditorPart findEditor(IFile file){
    ??????? IEditorReference[] editors = getActivePage().getEditorReferences();;
    ??????? for (int i = 0; i < editors.length; i++) {
    ??????????? IEditorPart part = (IEditorPart)editors[i].getPart(false);
    ??????????? if (part != null ){
    ??????????????? IEditorInput input = part.getEditorInput();
    ??????????????? if(input instanceof FileEditorInput && ((FileEditorInput)input).getFile().equals(file))
    ??????????????????? return part;
    ??????????? }???????????????
    ??????? }
    ??????? return null;
    ??? }

    4、得到工作區(qū)中所有工程的方法:
    ??????? IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
    ??????????????? .getProjects();
    這在開發(fā)自己的工程向?qū)У臅r候很有用處。
    5、工程特有文件判斷方法
    project.getFile("cownew.prj").exists();
    project.getDescription().hasNature();
    給工程增加Nature的方法:
    ?IProjectDescription desc = project.getDescription();
    String[] oldNatureIds = desc.getNatureIds();
    ??????????????? String[] newNatureIds? = new String[oldNatureIds.length +1];
    ??????????????? System.arraycopy(oldNatureIds, 0, newNatureIds, 0, oldNatureIds.length);
    ??????????????? newNatureIds[oldNatureIds.length] = "CowNewNature";
    ??????????????? desc.setNatureIds(newNatureIds);
    ??????????????? project.setDescription(desc, monitor);
    6、創(chuàng)建文件夾的方法:
    IFolder folder = project.getFolder("myfold");
    if (folder!=null && !folder.exists())
    ? folder.create(false, true, null);

    7、彈出包選擇對話框的方法:
    ElementListSelectionDialog dialog = new ElementListSelectionDialog(
    ??????????????????? getShell(), new LabelProvider());
    ??????????? dialog.setIgnoreCase(false);
    dialog.setElements(getAllPackages().toArray());
    ??????????? String path = currentPackage();
    ?dialog.setInitialSelections(new Object[] { path });
    dialog.open();
    fPKName.setText((String) dialog.getFirstResult());

    public List getAllPackages() {
    ??????? List list = new ArrayList();
    ??????? IResource res = getFirstSelection();
    ??????? IProject project = res.getProject();
    ??????? File file = project.getFolder("src").getLocation().toFile();
    ??????? File[] fs = file.listFiles();
    ??????? for (int i = 0; i < fs.length; i++) {
    ??????????? if (fs[i].isDirectory())
    ??????????????? iterator("", fs[i], list);
    ??????? }
    ??????? Collections.sort(list);
    ??????? return list;
    ??? }
    8 objectClass="org.eclipse.core.resources.IFile"代表菜單應(yīng)用到文件
    9 透視圖的的實現(xiàn)很簡單,就是在構(gòu)造函數(shù)里邊打開一些視圖,使一些action(這樣菜單和按鈕也就都可用)可以用,比如:
    String editorArea = layout.getEditorArea();
    ??????? IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT,
    ??????????????? 0.30f, editorArea);
    ??????? left.addView(PACKAGE_VIEW_ID);
    ?layout.setEditorAreaVisible(true);
    ?layout.addShowViewShortcut(IDESystem.BUSINESSVIEW_ID);

    posted @ 2006-07-21 00:33 CowNew開源團(tuán)隊 閱讀(1276) | 評論 (1)編輯 收藏

    為了幫助更多的朋友掌握eclipse的使用,我們團(tuán)隊做了一個eclipse視頻教程,全部都是開發(fā)過程的屏幕錄像,并且伴有語音講解。一共八講,今天全部上傳完畢。希望我們的努力幫助更多的朋友。
    觀看方式:
    1、登錄硅谷動力在線觀看:http://www.enet.com.cn/article/2006/0704/A20060704124810.shtml
    2、通過cownew團(tuán)隊網(wǎng)站中的超鏈接訪問:
    http://www.cownew.com/kc/

    感謝大家的支持。
    附前四講課件:
    ????????? 第一講? eclipse的基本使用
    1、eclipse工程的建立
    2、源文件夾等概念
    3、基本代碼的編寫
    ???????????? 第二講? eclipse基本操作(1)
    1、建立包、建立接口 及其他??
    2、工程的高級配置???
    3、工程的構(gòu)建
    3、代碼的自動完成、自動修正功能
    ?? 黃色的、紅色的標(biāo)識
    ?? (1)方法的自動生成
    ?? (2)導(dǎo)入import
    ?? (3)清除無用的import
    ?? (4)自動清除無用的方法、變量
    ?? (5)自動實現(xiàn)接口的、抽象類的方法,自動重載父類方法
    ???????? 第三講?? eclipse基本操作(2)
    1、Java的調(diào)試
    ??? (1) 斷點、條件斷點、異常斷點
    ?? (2)斷點中變量的查看,語句的執(zhí)行
    2、智能糾錯、自動完成:
    ?? (1)自動生成try...catch,自動列出異常列表,自動轉(zhuǎn)型...在紅色提示上點擊鼠標(biāo),常常可以得到驚喜
    ?? (2)自動生成set、get方法
    ?? (3)自動生成構(gòu)造函數(shù),?
    ?? (4)javadoc的自動生成

    第四講 eclipse高級操作(1) 重構(gòu)
    一、概述
    1、好的程序應(yīng)該是不斷重構(gòu)出來的。消除bad smell,提高代碼可讀性、可維護(hù)性和可擴(kuò)展性。《重構(gòu)-改善既有代碼的設(shè)計》(英文名《Refactoring: Improving the Design of Existing Code 》)
    2、Eclipse的自動重構(gòu)功能能夠很好地支持各種程序元素的重命名,并自動更新相關(guān)的引用。Eclipse能夠支持方法、字段在類之間移動,并自動更新引用。Eclipse較好地支持內(nèi)聯(lián)字段、函數(shù)的更新替換。Eclipse較好地支持抽取方法、變量等程序元素。
    3、Eclipse的重構(gòu)支持撤銷和重做,并且能夠預(yù)覽重構(gòu)結(jié)果,會對有可能導(dǎo)致錯誤的重構(gòu)結(jié)果進(jìn)行提示。所以使用Eclipse進(jìn)行重構(gòu)是非常安全的。
    二、重構(gòu)不高深-實戰(zhàn)重構(gòu)
    1、方法抽取 Extract Mehod:
    將caclCost中參數(shù)校驗部分抽取成方法verify。
    2、重命名 Rename
    ? (1)重命名類名Test1為CostCalculator。
    ? (2)重命名User為UserInfo
    3、內(nèi)聯(lián) Inlining
    ?? 內(nèi)聯(lián)方法add
    4、常量抽取 Extract Constant:
    ?? 將"normal"、"vip"抽取成常量
    5、抽取局部變量 Extract Local Variable
    ?? 將user.userType抽取成變量
    6、包裝字段 Encapsulate Field
    ?? 重構(gòu)User類,用set get包裝
    7、Extract Interface 抽取接口
    ?? CostCalculator中抽取ICostCalculator接口
    posted @ 2006-07-19 23:55 CowNew開源團(tuán)隊 閱讀(1794) | 評論 (3)編輯 收藏

    類型轉(zhuǎn)化

    Java是一種強(qiáng)類型語言,每個實例都必須有指定的類型。實際上,Java類型有兩種聲明類型運(yùn)行時類型 (也可以相應(yīng)的說是靜態(tài)類型動態(tài)類型 ). 像Python這樣的弱類型語言通常稱為無類型,但是這樣說并不嚴(yán)謹(jǐn),因為每個實例都有它的運(yùn)行時類型。你只是不用事先聲明一個實例的類型而已。

    要想調(diào)用一個對象中的方法,這個方法需要在聲明類型中存在。也就是說,你只能調(diào)用定義在父類中的方法,即使該實例是一個確定的子類型:

    List list = new ArrayList();
    list.add("data");       // 在這里沒問題
    list.ensureCapacity(4); // 這里就不行了ensureCapacity() 只在ArrayList中才有。
    

    如果我們要調(diào)用實際類型中的方法,我們首先要將它轉(zhuǎn)為正確的類型。在本例中,我們可以把 ArrayList 轉(zhuǎn)為List,因為ArrayList實現(xiàn)了List 接口. 也可以在運(yùn)行時動態(tài)的檢驗,使用 list instanceof ArrayList.

    可擴(kuò)展的接口

    糟糕的是,一個類不能總是實現(xiàn)你所需要實現(xiàn)的接口。可能是因為這只對少數(shù)幾種情況才有效,或者它是一個沒有被關(guān)聯(lián)的庫中的類型,或者這個接口在后期又被改變了。

    這種情況就可以使用IAdaptable。 你可以把 IAdaptable 動態(tài)的進(jìn)行類型轉(zhuǎn)化。使用如下方法避免直接的類型轉(zhuǎn)化:

    Object o = new ArrayList();
    List list = (List)o;
    

    我們可以這樣做:

    IAdaptable adaptable = new ArrayList();
    List list = (List)adaptable.getAdapter(java.util.List.class);
    

    你可認(rèn)為它是一種類型動態(tài)轉(zhuǎn)化; 我們把adaptable轉(zhuǎn)為List實例。

    為什么不直接轉(zhuǎn)化,而要用額外的getAdapter() 呢?這種機(jī)制可以使我們將目標(biāo)類轉(zhuǎn)化為沒有實現(xiàn)的接口。例如, 我們可能想使用HashMap 作為一個 List, 盡管他們并不兼容。

    IAdaptable adaptable = new HashMap();
    List list = (List)adaptable.getAdapter(java.util.List.class);
    

    實現(xiàn)IAdaptable

    大多數(shù)IAdaptable的實現(xiàn)看起來就想是為支持類型構(gòu)造多個if表達(dá)式的疊加。如果要為HashMap實現(xiàn)getAdapter() 可以這樣:

    public class HashMap implements IAdaptable {
      public Object getAdapter(Class clazz) {
        if (clazz == java.util.List.class) {
          List list = new ArrayList(this.size());
          list.addAll(this.values());
          return list;
        }
        return null;
      }
      // ...
    }
    

    返回的是一個對自身的代理,而不是直接轉(zhuǎn)化類型。如果請求的是不支持的類型,可以直接返回null表明失敗,這樣比拋出異常要好。

    PlatformObject

    當(dāng)你想添加新的要擴(kuò)展的類型時,只是簡單的修改一下就可以了。在任何情況下,如果已經(jīng)得到了類型,為什么不修改接口?不修改類(如果使用接口,不容易保證向后兼容)或者改變它的類型(HashMap不是 List,但是可以轉(zhuǎn)化)是有原因的。要解決這個問題,在Eclipse中,使用了一個抽象類 HashMap is not a List, but can be conveted into one).

    To solve this problem, there's an abstract class that is used by most parts of Eclipse called -->PlatformObject。它為你實現(xiàn)了 IAdaptable接口,你就可以不用再操心了。

    PlatformObject 代理所有的它對getAdapter()的請求到 IAdapterManager. IAdapterManager是平臺默認(rèn)提供的,通過 Platform.getAdapterManager()來訪問。你可以將它想象為一個巨大的 Map ,它負(fù)責(zé)關(guān)聯(lián)類和適當(dāng)?shù)倪m配器。PlatformObjectgetAdapter() 方法可以訪問到這個Map.

    適配已存在的類

    這樣的好處是可以為每一個PlatformObject對象動態(tài)的關(guān)聯(lián)新的適配器,而不用重新編譯。在Eclipse中的很多地方都是這樣來支持?jǐn)U展的。

    這里希望將裝有StringList轉(zhuǎn)為XML節(jié)點。 XML節(jié)點顯示為:

    <List>
      <Entry>First String</Entry>
      <Entry>Second String</Entry>
      <Entry>Third String</Entry>
    </List>
    

    因為ListtoString方法可能有別的用途,所以不能使用。 可以為List添加一個工廠,當(dāng)有轉(zhuǎn)為XML節(jié)點的請求時,一個Node對象就會自動返回。

    這里需要3個步驟:

    1. 從List中生成Node

    使用IAdapterFactory 來封裝轉(zhuǎn)換機(jī)制:

    import nu.xom.*;
    public class NodeListFactory implements IAdapterFactory {
      /** The supported types that we can adapt to */
      private static final Class[] types = {
        Node.class,
      };
      public Class[] getAdapterList() {
        return types;
      }
      /** The actual conversion to a Node */
      public Object getAdapter(Object list, Class clazz) {
        if (clazz == Node.class && list instanceof List) {
          Element root = new Element("List");
          Iterator it = list.iterator();
          while(it.hasNext()) {
            Element item = new Element("Entry");
            item.appendChild(it.next().toString());
            root.appendChild(item);
          }
          return root;
        } else {
          return null;
        }
      }
    }
    

    2. 注冊工廠到PlatformAdapterManager

    我們需要注冊工廠到適配器工廠,當(dāng)我們向 List實例請求Node時, 它就會知道是使用我們注冊的工廠。 Platform為我們管理IAdapterManager ,而且注冊過程相當(dāng)簡單:

    Platform.getAdapterManager().registerAdapters(
      new NodeListFactory(), List.class
    );
    

    上面的代碼要求平臺管理者關(guān)聯(lián)NodeListFactoryList。但我們要求List實例的適配器,它會調(diào)用這個工廠。根據(jù)我們對工廠的定義,會獲得一個Node對象。在Eclispe中,這一步必須在插件啟動的時候顯式的執(zhí)行,要隱式執(zhí)行可以通過 org.eclipse.core.runtime.adapters 擴(kuò)展點。

    3. 向List要求Node

    這里是要求適配器返回一個 Node 對象:

    Node getNodeFrom(IAdaptable list) {
      Object adaptable = list.getAdapter(Node.class);
      if (adaptable != null) {
        Node node = (Node)adaptable;
        return node;
      }
      return null;
    }
    

    總結(jié)

    如果你要在運(yùn)行時為已存在的類添加功能,只要定義一個能完成轉(zhuǎn)換功能的工廠,然后注冊工程到 PlatformAdapterManager就可以了. 這項功能可以用來為一個非UI組件注冊一個指定的UI組件,同時保持兩部分的完全分離。就像在org.rcpapps.rcpnews.uiorg.rcpapps.rcpnews 插件中的使用。在這些例子中, IPropertySource 在UI插件中,它需要與非UI插件的數(shù)據(jù)相關(guān)聯(lián)。當(dāng)UI插件初始化時,它注冊IPropertySourcePlatform, 當(dāng)數(shù)據(jù)對象在瀏覽器中被選中時,屬性視圖中就會顯示相應(yīng)的屬性。

    很明顯, java.util.List不能擴(kuò)展PlatformObject, 所以你不能指望例子中的代碼能夠編譯通過,你可以重新構(gòu)造 List的子類來實現(xiàn)目的.繼承PlatformObject 也不是必須的:

    public class AdaptableList implements IAdaptable, List {
      public Object getAdapter(Class adapter) {
         return Platform.getAdapterManager().getAdapter(this, adapter);
      }
      private List delegate = new ArrayList();
      public int size() {
        return delegate.size();
      }
      // ...
    }
    

    本例中使用了XOM 來生成XML。

    from:
    http://www.javathink.org/bbs/read.php?tid-1469-page-e.html

    posted @ 2006-07-19 21:49 CowNew開源團(tuán)隊 閱讀(356) | 評論 (0)編輯 收藏


    CowNew開源團(tuán)隊網(wǎng)站 http://www.cownew.com
    作者 楊中科 是CowNew開源團(tuán)隊發(fā)起人之一,郵箱about521? at 163 dot com
    論壇 http://www.cownew.com/newpeng/
    轉(zhuǎn)載請注明此版權(quán)信息


    ?? 最近準(zhǔn)備把進(jìn)銷存項目激活,這樣一方面可以讓更多的人有機(jī)會參與到開源開發(fā)中來,另一方面也把SQL翻譯器、SQL優(yōu)化器、JDBMonitor應(yīng)用到這個項目中,這樣這三個基礎(chǔ)模塊就可以在實際項目應(yīng)用中得到驗證和增強(qiáng)。
    ??? 我準(zhǔn)備用hibernate實現(xiàn)持久層,于是到hibernate的網(wǎng)站上把hibernate3下載下來,看了看有個hibernatetools,是個hibernate在eclipse下的輔助工具,也down了下來,用了用感覺不錯。可以直接從數(shù)據(jù)庫表生成POJO和hbm.xml(其實我不是很喜歡這種開發(fā)方式,我更喜歡我用建模工具來寫POJO,然后用工具生成hbm.xml和DDL,不過好像hibernate3現(xiàn)在還沒有這種工具,如果哪位朋友知道有這種工具,希望賜教)。
    美中不足的是它生成的javabean的字段名是完全和數(shù)據(jù)庫字段名一致、生成的javabean的類名是完全和數(shù)據(jù)庫表名一致。出于清晰以及可移植的考慮(也是公司的開發(fā)規(guī)范養(yǎng)成的習(xí)慣),我設(shè)計的表名全部以"T_"開頭,中間再加上子系統(tǒng)名,最后才是表意的表名,比如用“T_PS_BOM”表示生產(chǎn)管理系統(tǒng)中的物料清單表;字段名全部以“F”開頭,比如FId,FName。
    這樣就導(dǎo)致生成了如下的javabean:

    public class TPSBOM
    {
    ?? .......
    ?? public String getFID()
    ?? ...
    ?? public String getFNumber()
    }


    ??? 看起來很不直觀。我剛剛想放棄這個工具,想了想,“拿來就用,不好用就換”可不是做開源人該有的精神呀。鉆研一下。
    看看了Hibernate Code Generation頁簽中有一個“reveng Strategy”,什么意思?“反向工程策略”??好像有門兒,點擊“Browse”彈出一個類選擇對話框,竟然看到了它默認(rèn)顯示的“DefaultReverseEngineeringStrategy”類了,我在hibernatetools的安裝目錄找來找去,終于在plugins\org.hibernate.eclipse_3.2.0.beta6\lib\tools下的hibernate-tools.jar中找到了這個類的影子,用反編譯工具反編譯一下(懶得去網(wǎng)上下源碼了,呵呵)。一個個方法名展現(xiàn)在我面前:
    tableToClassName
    columnToPropertyName
    columnToHibernateTypeName
    。。。
    ??? 這不就是在把數(shù)據(jù)庫相應(yīng)的項映射成java相應(yīng)的項嗎?
    ??? 開工!
    ??? 新建一個類CowNewReverseEngineeringStrategy,繼承自DefaultReverseEngineeringStrategy,override? tableToClassName、
    columnToPropertyName這兩個方法,在這兩個方法中寫入自己的轉(zhuǎn)換邏輯。
    然后打包成jar包,放到plugins\org.hibernate.eclipse_3.2.0.beta6\lib\tools下,然后在plugins\org.hibernate.eclipse_3.2.0.beta6\lib\tools\MANIFEST.MF中把這個新增包的內(nèi)容加上,關(guān)閉eclipse,加個-clean參數(shù)啟動eclipse,然后點擊“Hibernate Code Generation”,把“reveng Strategy”填成“com.cownew.DevTools.hibtools.RevEng.CowNewReverseEngineeringStrategy”,“Run”!!!
    暈倒,竟然報錯“com.cownew.DevTools.hibtools.RevEng.CowNewReverseEngineeringStrategy
    Exception while generating code
    Reason?? org.hibernate.console.HibernateConsoleRunTimeException:Could not create or find com.?? with one argument deleate constructor”

    看來是反射調(diào)用的時候出了問題,重新打開hibernate-tools.jar,仔細(xì)觀察,竟然發(fā)現(xiàn)了一個DelegatingReverseEngineeringStrategy,它多??? 了一個參數(shù)為“ReverseEngineeringStrategy delegate”的構(gòu)造函數(shù),而其他調(diào)用都是轉(zhuǎn)發(fā)給ReverseEngineeringStrategy了,暈倒,搞不懂它在做什么,也沒時間研究了,給CowNewReverseEngineeringStrategy也曾街一個參數(shù)為“ReverseEngineeringStrategy delegate”的構(gòu)造函數(shù),重新打包,重新啟動eclipse,哈哈,一切搞定,終于生成我可愛的,
    public class PersonInfo

    ? public String getNumber()。。。
    ? public String getId()。。。

    了。
    ??? 附全部代碼:

    package com.cownew.DevTools.hibtools.RevEng;

    import java.beans.Introspector;

    import org.hibernate.cfg.reveng.DefaultReverseEngineeringStrategy;
    import org.hibernate.cfg.reveng.ReverseEngineeringSettings;
    import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
    import org.hibernate.cfg.reveng.ReverseEngineeringStrategyUtil;
    import org.hibernate.cfg.reveng.TableIdentifier;
    import org.hibernate.util.StringHelper;

    public class CowNewReverseEngineeringStrategy extends
    DefaultReverseEngineeringStrategy
    {

    ?public CowNewReverseEngineeringStrategy(ReverseEngineeringStrategy delegate)
    ?{??
    ??super();
    ?}

    ?private ReverseEngineeringSettings settings = new ReverseEngineeringSettings();

    ?public String tableToClassName(TableIdentifier table)
    ?{
    ??String tableName = table.getName();
    ??if (tableName != null && tableName.toUpperCase().startsWith("T_"))
    ??{
    ???String pkgName = settings.getDefaultPackageName();
    ???int lastIndex = tableName.lastIndexOf('_');
    ???tableName = tableName.substring(lastIndex + 1, tableName.length())
    ?????+ "Info";

    ???String className = toUpperCamelCase(tableName);

    ???if (pkgName.length() > 0)
    ????return StringHelper.qualify(pkgName, className);
    ???return className;

    ??} else
    ??{
    ???return super.tableToClassName(table);
    ??}
    ?};

    ?public String columnToPropertyName(TableIdentifier table, String column)
    ?{
    ??if (column != null && column.toUpperCase().startsWith("F"))
    ??{
    ???String cownewColName = column.substring(1, column.length());
    ???
    ???String decapitalize = Introspector
    ?????.decapitalize(toUpperCamelCase(cownewColName));
    ???return keywordCheck(decapitalize);
    ??} else
    ??{
    ???return super.columnToPropertyName(table, column);
    ??}
    ?}

    ?private String keywordCheck(String possibleKeyword)
    ?{
    ??if (ReverseEngineeringStrategyUtil
    ????.isReservedJavaKeyword(possibleKeyword))
    ???possibleKeyword += "_";
    ??return possibleKeyword;
    ?}

    ?public void setSettings(ReverseEngineeringSettings settings)
    ?{
    ??super.setSettings(settings);
    ??this.settings = settings;
    ?}

    ?public static void main(String[] args)
    ?{
    ??TableIdentifier table = new TableIdentifier("T_BD_Person");
    ??//TableIdentifier table = new TableIdentifier("T_Person");
    ??//TableIdentifier table = new TableIdentifier("Person");
    ??CowNewReverseEngineeringStrategy revEng = new CowNewReverseEngineeringStrategy(null);
    ??String className = revEng.tableToClassName(table);
    ??System.out.println(className);
    ??System.out.println(revEng.columnToPropertyName(table, "FId"));
    ??System.out.println(revEng.columnToPropertyName(table, "Id"));
    ?}
    }


    ?

    posted @ 2006-07-16 22:27 CowNew開源團(tuán)隊 閱讀(1521) | 評論 (4)編輯 收藏

    CowNew開源團(tuán)隊網(wǎng)站 http://www.cownew.com
    作者是CowNew開源團(tuán)隊發(fā)起人之一,郵箱about521? at 163 dot com
    論壇 http://www.cownew.com/newpeng/
    轉(zhuǎn)載請注明此版權(quán)信息


    java做的系統(tǒng)給人的印象是什么?占內(nèi)存!說道這句話就會有N多人站出來為java辯護(hù),并舉出一堆的性能測試報告來證明這一點。其實從理論上來講java做的系統(tǒng)并不比其他語言開發(fā)出來的系統(tǒng)更占用內(nèi)存,那么為什么卻有這么N多理由來證明它確實占內(nèi)存呢???兩個字,陋習(xí)。
    (1)別用new Boolean()。
    在很多場景中Boolean類型是必須的,比如JDBC中boolean類型的set與get都是通過Boolean封裝傳遞的,大部分ORM也是用Boolean來封裝boolean類型的,比如:
    ps.setBoolean("isClosed",new Boolean(true));
    ps.setBoolean("isClosed",new Boolean(isClosed));
    ps.setBoolean("isClosed",new Boolean(i==3));

    通常這些系統(tǒng)中構(gòu)造的Boolean實例的個數(shù)是相當(dāng)多的,所以系統(tǒng)中充滿了大量Boolean實例小對象,這是相當(dāng)消耗內(nèi)存的。
    Boolean類實際上只要兩個實例就夠了,一個true的實例,一個false的實例。
    Boolean類提供兩了個靜態(tài)變量:
    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);
    需要的時候只要取這兩個變量就可以了,
    比如:
    ps.setBoolean("isClosed",Boolean.TRUE);

    那么象2、3句那樣要根據(jù)一個boolean變量來創(chuàng)建一個Boolean怎么辦呢?可以使用Boolean提供的靜態(tài)方法:?? Boolean.valueOf()
    比如:
    ?
    ps.setBoolean("isClosed",Boolean.valueOf(isClosed));
    ps.setBoolean("isClosed",Boolean.valueOf(i==3));
    因為valueOf的內(nèi)部實現(xiàn)是:
    return (b ? TRUE : FALSE);
    所以可以節(jié)省大量內(nèi)存。

    相信如果Java規(guī)范直接把Boolean的構(gòu)造函數(shù)規(guī)定成private,就再也不會出現(xiàn)這種情況了。
    (2)別用new Integer。
    和Boolean類似,java開發(fā)中使用Integer封裝int的場合也非常多,并且通常用int表示的數(shù)值通常都非常小。
    SUN SDK中對Integer的實例化進(jìn)行了優(yōu)化,Integer類緩存了-128到127這256個狀態(tài)的Integer,如果使用Integer.valueOf(int i),傳入的int范圍正好在此內(nèi),就返回靜態(tài)實例。
    這樣如果我們使用Integer.valueOf代替new Integer的話也將大大降低內(nèi)存的占用。如果您的系統(tǒng)要在不同的SDK(比如IBM SDK)中使用的話,那么可以自己做了工具類封裝一下,比如IntegerUtils.valueOf(),這樣就可以在任何SDK中都可以使用這種特性。

    (3)用StringBuffer代替字符串相加。這個我就不多講了,因為已經(jīng)被人講過N次了。我只想將一個不是笑話的笑話,我在看國內(nèi)某“著名”java開發(fā)的WEB系統(tǒng)的源碼中,竟然發(fā)現(xiàn)其中大量的使用字符串相加,一個拼裝SQL語句的方法中竟然最多構(gòu)造了將近100個string實例。無語中!
    (4)過濫使用哈希表,有一定開發(fā)經(jīng)驗的開發(fā)人員經(jīng)常會使用hash表(hash表在JDK中的一個實現(xiàn)就是HashMap)來緩存一些數(shù)據(jù),從而提高系統(tǒng)的運(yùn)行速度。比如使用HashMap緩存一些物料信息、人員信息等基礎(chǔ)資料,這在提高系統(tǒng)速度的同時也加大了系統(tǒng)的內(nèi)存占用,特別是當(dāng)緩存的資料比較多的時候。其實我們可以使用操作系統(tǒng)中的緩存的概念來解決這個問題,也就是給被緩存的分配一個一定大小的緩存容器,按照一定的算法淘汰不需要繼續(xù)緩存的對象,這樣一方面會因為進(jìn)行了對象緩存而提高了系統(tǒng)的運(yùn)行效率,同時由于緩存容器不是無限制擴(kuò)大,從而也減少了系統(tǒng)的內(nèi)存占用。現(xiàn)在有很多開源的緩存實現(xiàn)項目,比如ehcache、oscache等,這些項目都實現(xiàn)了FIFO、MRU等常見的緩存算法。
    (5)避免過深的類層次結(jié)構(gòu)和過深的方法調(diào)用。因為這兩者都是非常占用內(nèi)存的(特別是方法調(diào)用更是堆棧空間的消耗大戶)。

    (6)變量只有在用到它的時候才定義和實例化。
    (7)盡量避免使用static變量,類內(nèi)私有常量可以用final來代替。

    posted @ 2006-07-14 23:50 CowNew開源團(tuán)隊 閱讀(1276) | 評論 (3)編輯 收藏

    ??????? 很多關(guān)心CowNew的朋友紛紛給我發(fā)email或者qq留言,說看到最近CowNew開源項目沒有動靜了,問我是不是虎頭蛇尾死掉了。謝謝大家的關(guān)心,CowNew沒有停止進(jìn)步的步伐,最近一段時間沒有動靜是因為我們在悶頭做產(chǎn)品的開發(fā)。經(jīng)過一個多月的努力,在kingchou、紫龍等隊友的團(tuán)結(jié)奮斗下,SQL解析引擎和JDBMonitor都已經(jīng)取得了階段性的成果。
    ??????? SQL解析引擎已經(jīng)可以生成完整的異構(gòu)SQLAST,除有少數(shù)小bug之外已經(jīng)基本達(dá)到了預(yù)期的目標(biāo)。另外在SQL解析引擎基礎(chǔ)上開發(fā)的CowNewSQL翻譯器也可以實現(xiàn)了基本的功能。可以翻譯大部分主流的sql語句,比如:
    (1)可以將符合CowNewSQL語法的select now()翻譯成對應(yīng)如下的特定平臺sql:
    mssql:Select GETDATE()
    mysql:Select NOW()
    oracle8i:Select SYSDATE FROM DUAL
    oracle9i:Select SYSDATE FROM DUAL
    (2)可以將符合CowNewSQL語法的
    update T2 set fid=t1.fid from (select * from t2
    left join t3 on t3.fid=t2.fid union select * from t5)
    翻譯成對應(yīng)如下的特定平臺sql:
    mssql:UPDATE T2 SET fid = t1.fid
    FROM(
    Select *
    From t2 left join t3 on t3.fid = t2.fid
    union Select *
    From t5
    )
    mysql:UPDATE T2 SET fid = t1.fid
    FROM(
    Select *
    From t2 left join t3 on t3.fid = t2.fid
    union Select *
    From t5
    )
    oracle8i:UPDATE T2 SET fid = t1.fid
    FROM(
    Select *
    From t2,t3 WHERE t3.fid = t2.fid(+)
    union Select *
    From t5
    )
    oracle9i:UPDATE T2 SET fid = t1.fid
    FROM(
    Select *
    From t2 left join t3 on t3.fid = t2.fid
    union Select *
    From t5
    )

    (2)可以將符合CowNewSQL語法的
    select top 20 ABS(-1),lcase(trim(name)),tochar(now()), ADD_SECONDS(now(),22),t2.name,DateAdd(Year,now(),3) from T_Table
    ,(select * from T_MD where FID=2222222222) as tmd
    left join T_T4 on tmd.id>T_Table.id
    left join T_T2 as t2 on T_T2.id=T_Table.id
    right join T_T3 as t3 on t2.id=t3.id
    翻譯成對應(yīng)如下的特定平臺sql:
    mssql:Select? top 20
    ?ABS(-1) , LOWER(LTRIM(RTRIM(name)) ,CONVERT(VARCHAR, GETDATE()),DATEADD(second,GETDATE(),22),t2.name,DATEADD(Year, GETDATE(), 3)
    From T_Table,
    Select *
    From T_MD
    Where FID = 2222222222 as tmd
    ?left join T_T4 on tmd.id > T_Table.id left join T_T2 as t2 on T_T2.id = T_Table.id right join T_T3 as t3 on t2.id = t3.id
    mysql:Select? ABS(-1) , LOWER(LTRIM(RTRIM(name)) ,CONCAT('', NOW()),DATE_ADD(NOW(), INTERVAL 22 SECOND),t2.name,DATE_ADD(3, INTERVAL NOW() YEAR)
    From T_Table,
    Select *
    From T_MD
    Where FID = 2222222222 as tmd
    ?left join T_T4 on tmd.id > T_Table.id left join T_T2 as t2 on T_T2.id = T_Table.id right join T_T3 as t3 on t2.id = t3.id limit 0, 20

    oracle8i:Select? ABS(-1) , LOWER(LTRIM(RTRIM(name)) , TO_CHAR(SYSDATE) ,(SYSDATE + 22/86400),t2.name,add_months(3, TRUNC(SYSDATE) * 12)
    From T_Table,
    Select *
    From T_MD
    Where FID = 2222222222 as tmd
    ,T_T4,T_T2 as t2,T_T3 as t3 WHERE ROWNUM <= 20
    ?AND tmd.id > T_Table.id(+) AND T_T2.id = T_Table.id(+) AND t2.id(+) = t3.id
    oracle9i:Select? ABS(-1) , LOWER(LTRIM(RTRIM(name)) , TO_CHAR(SYSDATE) ,(SYSDATE + 22/86400),t2.name,add_months(3, TRUNC(SYSDATE) * 12)
    From T_Table,
    Select *
    From T_MD
    Where FID = 2222222222 as tmd
    ?left join T_T4 on tmd.id > T_Table.id left join T_T2 as t2 on T_T2.id = T_Table.id right join T_T3 as t3 on t2.id = t3.id WHERE ROWNUM <= 20

    ??????? 但是這些sql翻譯只是按照語法手冊進(jìn)行的翻譯,還沒有經(jīng)過正式數(shù)據(jù)庫環(huán)境的測試,還需要進(jìn)一步的測試。
    ??????? 目前僅支持MSSQLSERVER,MYSQL,Oracle8i,Oracle9i,我們計劃進(jìn)一步支持DB2UDB,FireBird、ACCESS等數(shù)據(jù)庫。而且SQL解析引擎是用JDK5開發(fā)的,我們將是用Retrotranslator將其轉(zhuǎn)換個以保證可以在JDK1.4上運(yùn)行。

    ??????? JDBMonitor的需求已經(jīng)基本完成,但是新增的功能目前只能運(yùn)行在MSSQLSERVER上,我們準(zhǔn)備等COWNEWSQL翻譯器開發(fā)完畢后,將JDBMonitor涉及到數(shù)據(jù)庫操作的地方是用COWNEWSQL翻譯器來完成多數(shù)據(jù)庫支持,所以我們將會推遲JDBMonitor的原計劃的發(fā)版日期。
    ??????? 目前我們的項目還是很缺乏高手,比如CowNewSQL這塊就缺乏對各種數(shù)據(jù)庫比較熟悉的朋友,還有能對CowNewSQL進(jìn)行全面測試的朋友,希望對這方面開發(fā)比較感興趣的能加入到我們的開發(fā)中來,共同打造優(yōu)秀的開源產(chǎn)品。可以直接給我發(fā)送郵件about521 at 163.com

    posted @ 2006-07-03 00:35 CowNew開源團(tuán)隊 閱讀(2720) | 評論 (0)編輯 收藏

    以下內(nèi)容轉(zhuǎn)自韓寒的“太變態(tài)了!”
    "
    ?
    ... ...
    今年的超級女聲開始了,
    加油好男兒也開始了,
    但是我發(fā)現(xiàn),
    就我看的這些選手里,
    明顯有點問題,
    仿佛兩個節(jié)目弄反了,
    男的全是能擠出奶來的,
    還經(jīng)常對著鏡頭耶耶耶耶的,
    耶他大爺..
    女的全是弄成男人樣還壓低嗓子說話的.
    總之就是,
    讓異性看著都一點性欲沒有.
    太變態(tài)了.
    太變態(tài)了.
    我相信超級女聲里很多是趕時髦,
    可能性格并不如此,
    但那些男的,
    我真恨不得沖上去對著他們的褲襠就是一腳... ..."
    posted @ 2006-06-23 18:40 CowNew開源團(tuán)隊 閱讀(344) | 評論 (1)編輯 收藏

    CowNew開源團(tuán)隊網(wǎng)站 http://www.cownew.com
    作者 楊中科 是CowNew開源團(tuán)隊JDBMonitor開發(fā)組的開發(fā)人員,郵箱about521? at 163 dot com
    論壇 http://www.cownew.com/newpeng/
    轉(zhuǎn)載請注明此版權(quán)信息
    以前我一直是用使用數(shù)據(jù)源的系統(tǒng)測試JDBMonitor,昨天我準(zhǔn)備把JDBMonitor嵌入到一個小的jsp留言板中,這個留言板寫的非常簡單,數(shù)據(jù)庫操作也是connection隨取隨用、用完了就關(guān)這種最簡單的形式,這倒是幫助我發(fā)現(xiàn)了一個超級大bug。
    在記事本運(yùn)行中常常不規(guī)律的DataBaseDBListener的logSQL方法報空指針錯誤,是在logStatement.setString(1, randomGUID.toString());這一句拋出的,我跟蹤到mysql驅(qū)動的內(nèi)部(我使用的是mysql數(shù)據(jù)庫做DataBaseDBListener的輸出數(shù)據(jù)庫),發(fā)現(xiàn)在setString的實現(xiàn)中會去調(diào)用connection的方法,而此時connection已經(jīng)是null了,所以會報空指針錯誤。
    從其不規(guī)律的特點我判斷出應(yīng)該是多線程導(dǎo)致的問題。我跟蹤發(fā)現(xiàn),有的時候是先調(diào)用DataBaseDBListener的close后logSql才被調(diào)用。經(jīng)過分析找出了問題所在,問題就在DBLogger中內(nèi)部類LogConsumer的startConsumer方法,這個是修改以前的代碼:
    for (;;)
    ?{
    ??SQLInfo info = (SQLInfo) channel.take();????

    ??if(info==null)
    ??{
    ???ontinue;
    ??}
    ??for (int i = 0, n = dbListeners.length; i < n; i++)
    ??{
    ???dbListeners[i].logSql(info);
    ??}

    ?}


    在調(diào)用channel.take()以后,這個SQLInfo就從channel中去除了。這時如果DBLogger的方法被調(diào)用,那么即使dbListeners[i].logSql(info)仍然在運(yùn)行,但是DBLogger會認(rèn)為channel已經(jīng)空了,所有的dbListeners都可以被close了,而在DataBaseDBListener的close方法中會把輸出目標(biāo)數(shù)據(jù)庫connection關(guān)掉,那么此時如果DataBaseDBListener的logSql方法還在調(diào)用的話,那么一旦使用這個connection,那么就會出現(xiàn)錯誤了。
    我是如下修改的:
    修改BlockedChannel類,去掉其take方法,增加一個peek方法和一個remove方法,peek方法是從channel中查出一個對象,但是不把它從channel中移走,只有調(diào)用remove方法后才會被移走。
    修改DBLogger中內(nèi)部類LogConsumer的startConsumer方法為如下:
    for (;;)
    ?{
    ??SQLInfo info = (SQLInfo) channel.peek();
    ??if(info==null)
    ??{
    ???continue;
    ??}
    ??for (int i = 0, n = dbListeners.length; i < n; i++)
    ??{
    ???dbListeners[i].logSql(info);
    ??}
    ??channel.remove(info);
    ?}

    也就是只有SQLInfo被處理完了,才會從channel中移走。
    看來JDBMonitor還是要多多測試多多驗證,我近期準(zhǔn)備對JDBMonitor進(jìn)行性能測試,看看有沒有并發(fā)問題有沒有性能問題,不要再急著加新功能了,把這些基礎(chǔ)的功能做好再說,否則別人用著用著就出現(xiàn)中斷性錯誤了,那將會是比缺少功能更可怕的事情。一位同事曾經(jīng)說過一句話:“做的越多錯的越多。不要你做的多好,只要把已經(jīng)做完的東西做的更好就可以了。”,看來確實有一定道理呀。把基本的東西做好再說,否則被人罵不專業(yè)就慘了。

    posted @ 2006-06-15 22:52 CowNew開源團(tuán)隊 閱讀(832) | 評論 (0)編輯 收藏

    CowNew開源團(tuán)隊網(wǎng)站 http://www.cownew.com
    論壇 http://www.cownew.com/newpeng/
    轉(zhuǎn)載請注明此版權(quán)信息

    今天做的事情比較雜,所以感想也比較雜:
    1、java程序的遠(yuǎn)程調(diào)試。
    “JPDA是sun jdk自帶的遠(yuǎn)程調(diào)試機(jī)制。它提供了一套標(biāo)準(zhǔn)的調(diào)試接口,可以從虛擬機(jī)一級允許外界用特定協(xié)議探測虛擬機(jī)內(nèi)部的運(yùn)作細(xì)節(jié)。只要你裝了jdk 1.2以上的sun jdk,就已經(jīng)有了jpda支持。 只要是用標(biāo)準(zhǔn)JDK中java.exe運(yùn)行的應(yīng)用,就可以用jpda進(jìn)行遠(yuǎn)程調(diào)試。以web應(yīng)用的開發(fā)為例,servlet和ejb的調(diào)試一直不是一件太容易的事情。雖然jbuilder、eclipse等有一些常見的應(yīng)用服務(wù)器,如tomcat, weblogic 6.x,的調(diào)試插件,但是用法各不相同,而且很容易由于版本問題導(dǎo)致出現(xiàn)各種問題,而且對于有的服務(wù)器則沒有相應(yīng)的IDE插件。
    JPDA就不一樣。由于它是java平臺的標(biāo)準(zhǔn)功能之一,所以我們其實可以調(diào)試任何用jdk運(yùn)行的程序。只需要做兩件事:
    (1)、 在被調(diào)試的應(yīng)用上,增加幾個java虛擬機(jī)啟動參數(shù),讓它啟動后進(jìn)入調(diào)試服務(wù)器模式;
    (2) 在本機(jī)或網(wǎng)絡(luò)中另一臺機(jī)器上用某種jpda客戶端程序,attach到被調(diào)試的應(yīng)用程序(可以通過socket或共享內(nèi)存兩種方式)。jpda本身只是一個接口,調(diào)試工具的好用與否就要看其對jpda的應(yīng)用如何。jdb是sun jdk自帶的命令行jpda調(diào)試客戶程序,你可以用命令行設(shè)置斷點,查看變量值,等等。但不是很直觀。而jbuilder、eclipse的jpda調(diào)試器就做到了將jpda圖形化,可以直觀的設(shè)置斷點,跟蹤程序,查看量值,等等。 ”---本段改編自“http://www.cjsdn.com/post/print?bid=7&id=1376”

    以elipse+tomcat為例:
    (1)打開Tomcat 5.0\bin下的catalina.bat,在“set JPDA= ”下加入如下兩行:
    set JPDA_TRANSPORT=dt_socket
    set JPDA_ADDRESS=8787
    (2)啟動tomcat
    (3)在eclipse的debug中新建一個“Remote Java Application”,工程選擇被調(diào)試的遠(yuǎn)程程序的源碼工程,host填127.0.0.1,port為8787
    (4)運(yùn)行調(diào)試。
    這樣我們就可以在eclipse中下斷點調(diào)試tomcat中運(yùn)行的程序了。讓那些亂七八糟的插件哪涼快去哪呆著吧。
    注意一定要保證eclipse工程中的源碼和tomcat中運(yùn)行的程序一致。

    2、調(diào)用對象的wait方法的時候有可能會拋出InterruptedException異常,以前我是把這個異常再次拋出,今天運(yùn)行發(fā)現(xiàn)當(dāng)這個異常拋出的時候,線程就死掉了。因此不能簡單的將此異常re-throw,必須處理它,比如JDBMonitor中的BlockedChannel的take方法就要如下改寫:
    public synchronized Object take()
    ?{
    ??if (container.isEmpty())
    ??{
    ???try
    ???{
    ????wait();
    ???} catch (InterruptedException e)
    ???{
    ????return null;
    ???}
    ??}
    ??Object obj = container.pop();
    ??return obj;
    ?}

    3、windows下運(yùn)行l(wèi)inux的最好的工具
    最近一直想驗證JDBMonitor在linux底下是否有bug,但是聽人說過,linux安裝不當(dāng)很容易發(fā)生數(shù)據(jù)丟失,因此一直不敢裝。而用virtual PC,VMWare之類的軟件又太消耗內(nèi)存,而且需要虛擬機(jī)安裝完成再安裝linux。今天無意中搜索到一個windows下的linux虛擬機(jī):MetroPipe VPM 。
    下載地址:
    http://www.metropipe.net/ProductsPVPMDownload.shtml
    解壓后直接運(yùn)行其中的qemu-win.bat就能啟動Linux。不用安裝,啟動關(guān)閉都非常快,而且占用內(nèi)存相對來說比較小。
    唯一一個缺點就是默認(rèn)就進(jìn)入圖形模式,抽時間看看怎么配置讓它啟動以后進(jìn)入字符模式。
    詳細(xì)可以參考:http://www.highand.com/viewthread.php?tid=545

    ?

    posted @ 2006-06-13 01:06 CowNew開源團(tuán)隊 閱讀(963) | 評論 (0)編輯 收藏

    對于一個新手來說,安裝Linux勢必會帶來很大的風(fēng)險。膽子小的最后決定繼續(xù)享受Windows,膽子大的有一些不幸地丟失了硬盤中的所有數(shù)據(jù)。現(xiàn)在你不必提心吊膽了!在Windows下你可以輕易運(yùn)行Linux,無需安裝,你只要下載一個MetroPipe VPM(以下簡稱VPM),解壓后運(yùn)行一下就OK了。

    QUOTE:

    MetroPipe VPM 小檔案

    軟件版本:不詳 軟件大小:83MB
    軟件性質(zhì):免費(fèi) 適用平臺:Windows/Linux
    下載地址:http://www.metropipe.net/ProductsPVPMDownload.shtml
    軟件備注:在下載頁面中包含了多種下載方式,建議使用“Download.zip file via HTTP”右側(cè)的Download按鈕下載。


    VPM其實是一個多平臺的小型虛擬機(jī)軟件,這個壓縮包中包含了一個完整的Linux版本。解壓后直接運(yùn)行其中的qemu-win.bat就能啟動Linux(如果硬盤配置較低,啟動時間會比較長),根據(jù)彈出窗口的提示回車登錄Linux,出現(xiàn)桌面后就能和普通Linux一樣cao作了。磁盤目錄結(jié)構(gòu)、命令等都和普通的Linux完全相同,如果想練手的話非常合適。


    *為什么鼠標(biāo)逃不出Linux窗口了

    進(jìn)入Linux之后,你會發(fā)現(xiàn)鼠標(biāo)無法脫離Linux窗口了,要再次回到Windows,可以使用組合鍵“Ctrl+Shift”。


    *能否全屏顯示

    使用組合鍵“Ctrl+Shift+F"(要回到窗口模式只需再按一次)就能全屏cao作Linux,但是全屏之后 屏閃比較嚴(yán)重,還是窗口模式比較對得起自己的眼睛。

    *在這個Linux中能否上網(wǎng)

    運(yùn)行后直接映射Windows中當(dāng)前存在的網(wǎng)絡(luò)連接,無需手動配置。可以用Linux中自帶的FireFox看網(wǎng)頁、Thunderbird收郵件、axFTP上傳文件,但可惜只支持英語

    *小提示
    要關(guān)閉時可以直接關(guān)閉窗口,也可以右鍵點擊桌面空白處選擇“Power Down→Shutdown”。


    摘自《電腦愛好者》2006年第5期 Page 40

    posted @ 2006-06-12 23:59 CowNew開源團(tuán)隊 閱讀(1607) | 評論 (0)編輯 收藏

    僅列出標(biāo)題
    共30頁: First 上一頁 19 20 21 22 23 24 25 26 27 下一頁 Last 
    主站蜘蛛池模板: 日批视频网址免费观看| 精品久久久久久久久免费影院| 亚洲AV一宅男色影视| 免费国产成人高清在线观看网站 | 亚洲一级毛片中文字幕| 精品少妇人妻AV免费久久洗澡 | 午夜影视在线免费观看| AAAAA级少妇高潮大片免费看| 久久亚洲精品无码VA大香大香| 国产精品99久久免费| 成全高清在线观看免费| 亚洲日韩久久综合中文字幕| 国产自偷亚洲精品页65页| 两个人的视频高清在线观看免费| 九九视频高清视频免费观看| 亚洲毛片免费观看| 中文字幕亚洲不卡在线亚瑟| 99久久免费国产精品特黄| 中文字幕看片在线a免费| 亚洲日本中文字幕天天更新| 久久精品国产亚洲av四虎| 国产精品黄页在线播放免费| 在线观看免费中文视频| 免费看一级一级人妻片| 亚洲中文字幕无码爆乳app| 久久亚洲精品国产精品黑人| 亚洲精品国精品久久99热| 24小时日本在线www免费的| 日韩精品极品视频在线观看免费| 特级aaaaaaaaa毛片免费视频| 亚洲人成电影在线观看青青| 国产亚洲AV手机在线观看| 日本免费福利视频| 桃子视频在线观看高清免费完整| 两个人看的www免费高清| 美女黄频视频大全免费的| 亚洲人成综合网站7777香蕉| 99ri精品国产亚洲| 亚洲国产精品特色大片观看完整版| 免费中文字幕在线观看| 看全色黄大色大片免费久久|