今天就跟大家聊聊有關(guān)深入淺析Java中的Object類(lèi),可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)公司是專(zhuān)業(yè)的五指山網(wǎng)站建設(shè)公司,五指山接單;提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行五指山網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
Java作為一個(gè)龐大的知識(shí)體系,涉及到的知識(shí)點(diǎn)繁多,本文將從Java中最基本的類(lèi)java.lang.Object開(kāi)始談起。
Object類(lèi)是Java中其他所有類(lèi)的祖先類(lèi),沒(méi)有Object類(lèi)Java面向?qū)ο鬅o(wú)從談起。作為其他所有類(lèi)的基類(lèi),Object具有哪些屬性和行為,是Java語(yǔ)言設(shè)計(jì)背后的思維體現(xiàn)。
Object類(lèi)位于java.lang包中,java.lang包包含著Java最基礎(chǔ)和核心的類(lèi),在編譯時(shí)會(huì)自動(dòng)導(dǎo)入。Object類(lèi)沒(méi)有定義屬性,一共有13個(gè)方法,具體的類(lèi)定義結(jié)構(gòu)如下圖:
1.類(lèi)構(gòu)造器public Object();
大部分情況下,Java中通過(guò)形如 new A(args..)形式創(chuàng)建一個(gè)屬于該類(lèi)型的對(duì)象。其中A即是類(lèi)名,A(args..)即此類(lèi)定義中相對(duì)應(yīng)的構(gòu)造函數(shù)。通過(guò)此種形式創(chuàng)建的對(duì)象都是通過(guò)類(lèi)中的構(gòu)造函數(shù)完成。為體現(xiàn)此特性,Java中規(guī)定:在類(lèi)定義過(guò)程中,對(duì)于未定義構(gòu)造函數(shù)的類(lèi),默認(rèn)會(huì)有一個(gè)無(wú)參數(shù)的構(gòu)造函數(shù),作為所有類(lèi)的基類(lèi),Object類(lèi)自然要反映出此特性,在源碼中,未給出Object類(lèi)構(gòu)造函數(shù)定義,但實(shí)際上,此構(gòu)造函數(shù)是存在的。
當(dāng)然,并不是所有的類(lèi)都是通過(guò)此種方式去構(gòu)建,也自然的,并不是所有的類(lèi)構(gòu)造函數(shù)都是public。
2.private static native void registerNatives();
registerNatives函數(shù)前面有native關(guān)鍵字修飾,Java中,用native關(guān)鍵字修飾的函數(shù)表明該方法的實(shí)現(xiàn)并不是在Java中去完成,而是由C/C++去完成,并被編譯成了.dll,由Java去調(diào)用。方法的具體實(shí)現(xiàn)體在dll文件中,對(duì)于不同平臺(tái),其具體實(shí)現(xiàn)應(yīng)該有所不同。用native修飾,即表示操作系統(tǒng),需要提供此方法,Java本身需要使用。具體到registerNatives()方法本身,其主要作用是將C/C++中的方法映射到Java中的native方法,實(shí)現(xiàn)方法命名的解耦。
既然如此,可能有人會(huì)問(wèn),registerNatives()修飾符為private,且并沒(méi)有執(zhí)行,作用何以達(dá)到?其實(shí),在Java源碼中,此方法的聲明后有緊接著一段靜態(tài)代碼塊:
private static native void registerNatives(); static { registerNatives(); }
3.protected native Object clone() throws CloneNotSupportedException;
clone()方法又是一個(gè)被聲明為native的方法,因此,我們知道了clone()方法并不是Java的原生方法,具體的實(shí)現(xiàn)是有C/C++完成的。clone英文翻譯為"克隆",其目的是創(chuàng)建并返回此對(duì)象的一個(gè)副本。形象點(diǎn)理解,這有一輛寶馬汽車(chē),你看著不錯(cuò),想要個(gè)一模一樣的。你調(diào)用此方法即可像變魔術(shù)一樣變出一輛一模一樣的寶馬出來(lái)。配置一樣,長(zhǎng)相一樣。但從此刻起,原來(lái)的那輛寶馬如果進(jìn)行了新的裝飾,與你克隆出來(lái)的這輛寶馬沒(méi)有任何關(guān)系了。你克隆出來(lái)的對(duì)象變不變完全在于你對(duì)克隆出來(lái)的寶馬有沒(méi)有進(jìn)行過(guò)什么操作了。Java術(shù)語(yǔ)表述為:clone函數(shù)返回的是一個(gè)引用,指向的是新的clone出來(lái)的對(duì)象,此對(duì)象與原對(duì)象分別占用不同的堆空間。
明白了clone的含義后,接下來(lái)看看如果調(diào)用clone()函數(shù)對(duì)象進(jìn)行此克隆操作。
首先看一下下面的這個(gè)例子:
package com.bjpowernode.test; import com.corn.Person; public class ObjectTest { public static void main(String[] args) { Object o1 = new Object(); // The method clone() from the type Object is not visible Object clone = o1.clone(); } }
例子很簡(jiǎn)單,在main()方法中,new一個(gè)Oject對(duì)象后,想直接調(diào)用此對(duì)象的clone方法克隆一個(gè)對(duì)象,但是出現(xiàn)錯(cuò)誤提示:"The method clone() from the type Object is not visible"
why? 根據(jù)提示,第一反應(yīng)是ObjectTest類(lèi)中定義的Oject對(duì)象無(wú)法訪(fǎng)問(wèn)其clone()方法。回到Object類(lèi)中clone()方法的定義,可以看到其被聲明為protected,估計(jì)問(wèn)題就在這上面了,protected修飾的屬性或方法表示:在同一個(gè)包內(nèi)或者不同包的子類(lèi)可以訪(fǎng)問(wèn)。顯然,Object類(lèi)與ObjectTest類(lèi)在不同的包中,但是ObjectTest繼承自O(shè)bject,是Object類(lèi)的子類(lèi),于是,現(xiàn)在卻出現(xiàn)子類(lèi)中通過(guò)Object引用不能訪(fǎng)問(wèn)protected方法,原因在于對(duì)"不同包中的子類(lèi)可以訪(fǎng)問(wèn)"沒(méi)有正確理解。
"不同包中的子類(lèi)可以訪(fǎng)問(wèn)",是指當(dāng)兩個(gè)類(lèi)不在同一個(gè)包中的時(shí)候,繼承自父類(lèi)的子類(lèi)內(nèi)部且主調(diào)(調(diào)用者)為子類(lèi)的引用時(shí)才能訪(fǎng)問(wèn)父類(lèi)用protected修飾的成員(屬性/方法)。 在子類(lèi)內(nèi)部,主調(diào)為父類(lèi)的引用時(shí)并不能訪(fǎng)問(wèn)此protected修飾的成員。!(super關(guān)鍵字除外)
于是,上例改成如下形式,我們發(fā)現(xiàn),可以正常編譯:
package com.bjpowernode.test; public class ObjectTest { public static void main(String[] args) { ObjectTest ot1 = new ObjectTest(); try { ObjectTest ot2 = (ObjectTest) ot1.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
是的,因?yàn)榇藭r(shí)的主調(diào)已經(jīng)是子類(lèi)的引用了。
上述代碼在運(yùn)行過(guò)程中會(huì)拋出"java.lang.CloneNotSupportedException",表明clone()方法并未正確執(zhí)行完畢,問(wèn)題的原因在與Java中的語(yǔ)法規(guī)定:
clone()的正確調(diào)用是需要實(shí)現(xiàn)Cloneable接口,如果沒(méi)有實(shí)現(xiàn)Cloneable接口,并且子類(lèi)直接調(diào)用Object類(lèi)的clone()方法,則會(huì)拋出CloneNotSupportedException異常。
Cloneable接口僅是一個(gè)表示接口,接口本身不包含任何方法,用來(lái)指示Object.clone()可以合法的被子類(lèi)引用所調(diào)用。
于是,上述代碼改成如下形式,即可正確指定clone()方法以實(shí)現(xiàn)克隆。
package com.bjpowernode.test; public class ObjectTest implements Cloneable { public static void main(String[] args) { ObjectTest ot1 = new ObjectTest(); try { ObjectTest ot2 = (ObjectTest) ot1.clone(); System.out.println("ot2:" + ot2); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
4.public final native Class<?> getClass();
getClass()也是一個(gè)native方法,返回的是此Object對(duì)象的類(lèi)對(duì)象/運(yùn)行時(shí)類(lèi)對(duì)象Class<?>。效果與Object.class相同。
首先解釋下"類(lèi)對(duì)象"的概念:在Java中,類(lèi)是是對(duì)具有一組相同特征或行為的實(shí)例的抽象并進(jìn)行描述,對(duì)象則是此類(lèi)所描述的特征或行為的具體實(shí)例。作為概念層次的類(lèi),其本身也具有某些共同的特性,如都具有類(lèi)名稱(chēng)、由類(lèi)加載器去加載,都具有包,具有父類(lèi),屬性和方法等。于是,Java中有專(zhuān)門(mén)定義了一個(gè)類(lèi),Class,去描述其他類(lèi)所具有的這些特性,因此,從此角度去看,類(lèi)本身也都是屬于Class類(lèi)的對(duì)象。為與經(jīng)常意義上的對(duì)象相區(qū)分,在此稱(chēng)之為"類(lèi)對(duì)象"。
5.public boolean equals(Object obj);
==與equals在Java中經(jīng)常被使用,大家也都知道==與equals的區(qū)別:==表示的是變量值完成相同(對(duì)于基礎(chǔ)類(lèi)型,地址中存儲(chǔ)的是值,引用類(lèi)型則存儲(chǔ)指向?qū)嶋H對(duì)象的地址);
equals表示的是對(duì)象的內(nèi)容完全相同,此處的內(nèi)容多指對(duì)象的特征/屬性。
實(shí)際上,上面說(shuō)法是不嚴(yán)謹(jǐn)?shù)?,更多的只是常?jiàn)于String類(lèi)中。首先看一下Object類(lèi)中關(guān)于equals()方法的定義:
public boolean equals(Object obj) { return (this == obj); }
由此可見(jiàn),Object原生的equals()方法內(nèi)部調(diào)用的正是==,與==具有相同的含義。既然如此,為什么還要定義此equals()方法?
equlas()方法的正確理解應(yīng)該是:判斷兩個(gè)對(duì)象是否相等。那么判斷對(duì)象相等的標(biāo)尺又是什么?
如上,在object類(lèi)中,此標(biāo)尺即為==。當(dāng)然,這個(gè)標(biāo)尺不是固定的,其他類(lèi)中可以按照實(shí)際的需要對(duì)此標(biāo)尺含義進(jìn)行重定義。如String類(lèi)中則是依據(jù)字符串內(nèi)容是否相等來(lái)重定義了此標(biāo)尺含義。如此可以增加類(lèi)的功能型和實(shí)際編碼的靈活性。當(dāng)然了,如果自定義的類(lèi)沒(méi)有重寫(xiě)equals()方法來(lái)重新定義此標(biāo)尺,那么默認(rèn)的將是其父類(lèi)的equals(),直到object基類(lèi)。
如下場(chǎng)景的實(shí)際業(yè)務(wù)需求,對(duì)于User bean,由實(shí)際的業(yè)務(wù)需求可知當(dāng)屬性u(píng)id相同時(shí),表示的是同一個(gè)User,即兩個(gè)User對(duì)象相等。則可以重寫(xiě)equals以重定義User對(duì)象相等的標(biāo)尺。
package com.bjpowernode.test; public class User { private int uid; private String name; private int age; public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } protected String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof User)) { return false; } if (((User) obj).getUid() == this.getUid()) { return true; } return false; } }
package com.bjpowernode.test; public class ObjectTest implements Cloneable { public static void main(String[] args) { User u1 = new User(); u1.setUid(111); u1.setName("張三"); User u2 = new User(); u2.setUid(111); u2.setName("張三豐"); System.out.println(u1.equals(u2)); //返回true } }
ObjectTest中打印出true,因?yàn)閁ser類(lèi)定義中重寫(xiě)了equals()方法,這很好理解,很可能張三是一個(gè)人小名,張三豐才是其大名,判斷這兩個(gè)人是不是同一個(gè)人,這時(shí)只用判斷uid是否相同即可。
如上重寫(xiě)equals方法表面上看上去是可以了,實(shí)則不然。因?yàn)樗茐牧薐ava中的約定:重寫(xiě)equals()方法必須重寫(xiě)hasCode()方法。
6.public native int hashCode();
hashCode()方法返回一個(gè)整形數(shù)值,表示該對(duì)象的哈希碼值。
hashCode()具有如下約定:
1. 在Java應(yīng)用程序程序執(zhí)行期間,對(duì)于同一對(duì)象多次調(diào)用hashCode()方法時(shí),其返回的哈希碼是相同的,前提是將對(duì)象進(jìn)行equals比較時(shí)所用的標(biāo)尺信息未做修改。在Java應(yīng)用程序的一次執(zhí)行到另外一次執(zhí)行,同一對(duì)象的hashCode()返回的哈希碼無(wú)須保持一致;
2. 如果兩個(gè)對(duì)象相等(依據(jù):調(diào)用equals()方法),那么這兩個(gè)對(duì)象調(diào)用hashCode()返回的哈希碼也必須相等;
3. 反之,兩個(gè)對(duì)象調(diào)用hasCode()返回的哈希碼相等,這兩個(gè)對(duì)象不一定相等。
即嚴(yán)格的數(shù)學(xué)邏輯表示為: 兩個(gè)對(duì)象相等 <=> equals()相等 => hashCode()相等。因此,重寫(xiě)equlas()方法必須重寫(xiě)hashCode()方法,以保證此邏輯嚴(yán)格成立,同時(shí)可以推理出:hasCode()不相等 => equals()不相等 <=> 兩個(gè)對(duì)象不相等。
可能有人在此產(chǎn)生疑問(wèn):既然比較兩個(gè)對(duì)象是否相等的唯一條件(也是沖要條件)是equals,那么為什么還要弄出一個(gè)hashCode(),并且進(jìn)行如此約定,弄得這么麻煩?
其實(shí),這主要體現(xiàn)在hashCode()方法的作用上,其主要用于增強(qiáng)哈希表的性能。
以集合類(lèi)中,以Set為例,當(dāng)新加一個(gè)對(duì)象時(shí),需要判斷現(xiàn)有集合中是否已經(jīng)存在與此對(duì)象相等的對(duì)象,如果沒(méi)有hashCode()方法,需要將Set進(jìn)行一次遍歷,并逐一用equals()方法判斷兩個(gè)對(duì)象是否相等,此種算法時(shí)間復(fù)雜度為o(n)。通過(guò)借助于hasCode方法,先計(jì)算出即將新加入對(duì)象的哈希碼,然后根據(jù)哈希算法計(jì)算出此對(duì)象的位置,直接判斷此位置上是否已有對(duì)象即可。(注:Set的底層用的是Map的原理實(shí)現(xiàn))
在此需要糾正一個(gè)理解上的誤區(qū):對(duì)象的hashCode()返回的不是對(duì)象所在的物理內(nèi)存地址。甚至也不一定是對(duì)象的邏輯地址,hashCode()相同的兩個(gè)對(duì)象,不一定相等,換言之,不相等的兩個(gè)對(duì)象,hashCode()返回的哈希碼可能相同。
因此,在上述代碼中,重寫(xiě)了equals()方法后,需要重寫(xiě)hashCode()方法。
package com.bjpowernode.test; public class User { private int uid; private String name; private int age; public int getUid() { return uid; } public void setUid(int uid) { this.uid = uid; } protected String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof User)) { return false; } if (((User) obj).getUid() == this.getUid()) { return true; } return false; } @Override public int hashCode() { int result = 17; result = 31 * result + this.getUid(); return result; } }
注:上述hashCode()的重寫(xiě)中出現(xiàn)了result*31,是因?yàn)閞esult*31 = (result<<5) - result。之所以選擇31,是因?yàn)樽笠七\(yùn)算和減運(yùn)算計(jì)算效率遠(yuǎn)大于乘法運(yùn)算。當(dāng)然,也可以選擇其他數(shù)字。
7.public String toString();
toString()方法返回該對(duì)象的字符串表示。先看一下Object中的具體方法體:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
toString()方法相信大家都經(jīng)常用到,即使沒(méi)有顯式調(diào)用,但當(dāng)我們使用System.out.println(obj)時(shí),其內(nèi)部也是通過(guò)toString()來(lái)實(shí)現(xiàn)的。
getClass()返回對(duì)象的類(lèi)對(duì)象,getClassName()以String形式返回類(lèi)對(duì)象的名稱(chēng)(含包名)。Integer.toHexString(hashCode())則是以對(duì)象的哈希碼為實(shí)參,以16進(jìn)制無(wú)符號(hào)整數(shù)形式返回此哈希碼的字符串表示形式。
如上例中的u1的哈希碼是638,則對(duì)應(yīng)的16進(jìn)制為27e,調(diào)用toString()方法返回的結(jié)果為:com.bjpowernode.test.User@27e。
因此:toString()是由對(duì)象的類(lèi)型和其哈希碼唯一確定,同一類(lèi)型但不相等的兩個(gè)對(duì)象分別調(diào)用toString()方法返回的結(jié)果可能相同。
8/9/10/11/12. wait(...) / notify() / notifyAll()
一說(shuō)到wait(...) / notify() | notifyAll()幾個(gè)方法,首先想到的是線(xiàn)程。確實(shí),這幾個(gè)方法主要用于java多線(xiàn)程之間的協(xié)作。先具體看下這幾個(gè)方法的主要含義:
wait():調(diào)用此方法所在的當(dāng)前線(xiàn)程等待,直到在其他線(xiàn)程上調(diào)用此方法的主調(diào)(某一對(duì)象)的notify()/notifyAll()方法。
wait(long timeout)/wait(long timeout, int nanos):調(diào)用此方法所在的當(dāng)前線(xiàn)程等待,直到在其他線(xiàn)程上調(diào)用此方法的主調(diào)(某一對(duì)象)的notisfy()/notisfyAll()方法,或超過(guò)指定的超時(shí)時(shí)間量。
notify()/notifyAll():?jiǎn)拘言诖藢?duì)象監(jiān)視器上等待的單個(gè)線(xiàn)程/所有線(xiàn)程。
wait(...) / notify() | notifyAll()一般情況下都是配套使用。下面來(lái)看一個(gè)簡(jiǎn)單的例子:
package com.bjpowernode.test; public class ThreadTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub MyRunnable r = new MyRunnable(); Thread t = new Thread(r); t.start(); synchronized (r) { try { System.out.println("main thread 等待t線(xiàn)程執(zhí)行完"); r.wait(); System.out.println("被notity喚醒,得以繼續(xù)執(zhí)行"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("main thread 本想等待,但被意外打斷了"); } System.out.println("線(xiàn)程t執(zhí)行相加結(jié)果" + r.getTotal()); } } } class MyRunnable implements Runnable { private int total; @Override public void run() { // TODO Auto-generated method stub synchronized (this) { System.out.println("Thread name is:" + Thread.currentThread().getName()); for (int i = 0; i < 10; i++) { total += i; } notify(); System.out.println("執(zhí)行notif后同步代碼塊中依然可以繼續(xù)執(zhí)行直至完畢"); } System.out.println("執(zhí)行notif后且同步代碼塊外的代碼執(zhí)行時(shí)機(jī)取決于線(xiàn)程調(diào)度"); } public int getTotal() { return total; } }
運(yùn)行結(jié)果為:
1 main thread 等待t線(xiàn)程執(zhí)行完
2 Thread name is:Thread-0
3 執(zhí)行notif后同步代碼塊中依然可以繼續(xù)執(zhí)行直至完畢
4 執(zhí)行notif后且同步代碼塊外的代碼執(zhí)行時(shí)機(jī)取決于線(xiàn)程調(diào)度 //此行輸出位置有具體的JVM線(xiàn)程調(diào)度決定,有可能最后執(zhí)行
5 被notity喚醒,得以繼續(xù)執(zhí)行
6 線(xiàn)程t執(zhí)行相加結(jié)果45
既然是作用于多線(xiàn)程中,為什么卻是Object這個(gè)基類(lèi)所具有的方法?原因在于理論上任何對(duì)象都可以視為線(xiàn)程同步中的監(jiān)聽(tīng)器,且wait(...)/notify()|notifyAll()方法只能在同步代碼塊中才能使用。
從上述例子的輸出結(jié)果中可以得出如下結(jié)論:
1、wait(...)方法調(diào)用后當(dāng)前線(xiàn)程將立即阻塞,且適當(dāng)其所持有的同步代碼塊中的鎖,直到被喚醒或超時(shí)或打斷后且重新獲取到鎖后才能繼續(xù)執(zhí)行;
2、notify()/notifyAll()方法調(diào)用后,其所在線(xiàn)程不會(huì)立即釋放所持有的鎖,直到其所在同步代碼塊中的代碼執(zhí)行完畢,此時(shí)釋放鎖,因此,如果其同步代碼塊后還有代碼,其執(zhí)行則依賴(lài)于JVM的線(xiàn)程調(diào)度。
在Java源碼中,可以看到wait()具體定義如下:
public final void wait() throws InterruptedException { wait(0); }
且wait(long timeout, int nanos)方法定義內(nèi)部實(shí)質(zhì)上也是通過(guò)調(diào)用wait(long timeout)完成。而wait(long timeout)是一個(gè)native方法。因此,wait(...)方法本質(zhì)上都是native方式實(shí)現(xiàn)。
notify()/notifyAll()方法也都是native方法。
Java中線(xiàn)程具有較多的知識(shí)點(diǎn),是一塊比較大且重要的知識(shí)點(diǎn)。后期會(huì)有博文專(zhuān)門(mén)針對(duì)Java多線(xiàn)程作出詳細(xì)總結(jié)。此處不再細(xì)述。
13. protected void finalize();
finalize方法主要與Java垃圾回收機(jī)制有關(guān)。首先我們看一下finalized方法在Object中的具體定義:
protected void finalize() throws Throwable { }
我們發(fā)現(xiàn)Object類(lèi)中finalize方法被定義成一個(gè)空方法,為什么要如此定義呢?finalize方法的調(diào)用時(shí)機(jī)是怎么樣的呢?
首先,Object中定義finalize方法表明Java中每一個(gè)對(duì)象都將具有finalize這種行為,其具體調(diào)用時(shí)機(jī)在:JVM準(zhǔn)備對(duì)此對(duì)形象所占用的內(nèi)存空間進(jìn)行垃圾回收前,將被調(diào)用。由此可以看出,此方法并不是由我們主動(dòng)去調(diào)用的(雖然可以主動(dòng)去調(diào)用,此時(shí)與其他自定義方法無(wú)異)。
看完上述內(nèi)容,你們對(duì)深入淺析Java中的Object類(lèi)有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
網(wǎng)站題目:深入淺析Java中的Object類(lèi)
轉(zhuǎn)載來(lái)源:http://vcdvsql.cn/article36/iijgsg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站排名、軟件開(kāi)發(fā)、網(wǎng)頁(yè)設(shè)計(jì)公司、網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)