Day09-Java
文章目錄
- Day09-Java
- 1、匿名內部類
- 2、Object類簡介
- 2.1 取得物件資訊toString()
- 2.2 物件的比較equals()
- 2.3 Object介面參考資料型別
- 3、包裝類
- 3.1 裝箱與拆箱
- 3.2 字串與基本資料型別的轉換
- 3.3 包的定義
- 3.4 包的匯入
- 4、訪問控制權限
- 5、jar命令
1、匿名內部類
內部類:在一個類的內部定義了另外的類,稱為內部類,匿名內部類指的是沒有名字的內部類,為了清楚內部類的主要作用,下面首先觀察一個代碼,
interface IMessage{
public void print();
}
class MessageImpl implements IMessage{//定義介面實作類
public void print(){
System.out.println("Hello World");
}
}
class Demo{
public static void get(IMessage msg){//接受介面物件
msg.print();
}
}
public class TestDemo1{
public static void main(String args[]){
IMessage msg = new MessageImpl();//子類為介面實體化
Demo.get(msg);//傳遞msg物件
}
}
如果說現在MessageImpl這個子類只使用一次,有必要按照以上的方式進行定義嗎?
這個時候MessageImpl就沒有什么意義了,但是可以利用匿名內部類的概念來解決此問題,匿名內部類是在抽象累和介面的基礎之上發展起來的,
interface IMessage{
public void print();
}
class Demo{
public static void get(IMessage msg){//接受介面物件
msg.print();
}
}
public class TestDemo1{
public static void main(String args[]){
IMessage msg = new IMessage(){//匿名內部類
public void print(){
System.out.println("hello,world!");
}
};
Demo.get(msg);//傳遞msg物件
}
}
結論:基本上搞匿名內部類都應該在介面或抽象類形式上完成,
在抽象類中使用匿名內部類
abstract class Message{
public void print(){
System.out.print(this.getInfo());
}
public abstract String getInfo();
}
class Demo{
public static void get(Message msg){//接受介面物件
msg.print();
}
}
public class TestDemo1{
public static void main(String args[]){
Demo.get(new Message(){
public String getInfo(){
return "www.baidu.com";
}
});//傳遞msg物件
}
}
強調:一個普通類進行不要再去有子類進行繼承,能夠繼承的只是抽象類和介面,所以在普通類上繼續使用
匿名內部類的形式來定義子類,但是在正常的開發邏輯上是錯誤的,
2、Object類簡介
在Java的定義之中,除了Object類之外,所有的類實際上都存在繼承關系,即:如果現在定義了一個類,沒有默認繼承任何一個父類的話,則默認講繼承Object類,以下兩種類最終定義效果是完全一樣的,
Object類的無參構造是專門子類提供服務的,
| 方法名稱 | 型別 | 描述 |
|---|---|---|
| public String toString() | 普通 | 取得物件資訊 |
| public boolean equals(Object obj) | 普通 | 物件的比較 |
| public int hashCode() | 普通 | 回傳物件的哈希碼值 |
2.1 取得物件資訊toString()
toString()的核心目的在于取得物件資訊,相當于替換了getInfo()方法的功能,
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return "name = " + this.name + ",age = " + this.age ;
}
}
public class TestDemo2{
public static void main(String args[]){
Person p = new Person("zsr",18);
System.out.print(p.toString());
}
}
2.2 物件的比較equals()
實際上對于equals()方法應該并不陌生,這個方法在String類中見過,String是Object類的子類,所以String類的equals()方法就是覆寫了Object類中的equals()方法,在Object類之中,默認的equals()方法實作比較的是兩個物件的記憶體地址數值,但是并不符合與真正的物件比較需要,物件比較之前也寫過,但是之前那是自己定義的一個新的方法名稱,今天可以給出標準的方法名稱:equals(),
class Person{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public boolean equals(Object anObject){
if(anObject == null){
return false;
}
if(this == anObject){
return true;
}
//判斷anObject的實體是不是Person
if( !(anObject instanceof Person)){
return false;
}
//必須將Object型別變為Person型別后才可以呼叫name和age屬性
Person per = (Person) anObject;
return this.name.equals(per.name) && this.age == per.age;
}
public String toString(){//覆寫Object類方法
return "name = " + this.name + ",age = " + this.age ;
}
}
public class TestDemo3{
public static void main(String args[]){
Person per1 = new Person("zsr",18);
Person per2 = new Person("zsr",18);
//true
System.out.println(per1.equals(per2));
//false
System.out.println(per1.equals("Hello,world!"));
}
}
但是需要有一個注意,很多人在寫物件的比較會使用如下的形式:
- public boolean equals(Person anObject)
因為父類中的equals()方法用的是Object,所以以上的方法嚴格來講已經不叫覆寫,叫多載,
2.3 Object介面參考資料型別
在之前的分析來講Object可以接收任意的物件,從結構上來講Object是所有類的父類,但是Object概念并不僅僅局限于此,他已接收所有的參考資料型別,包括:介面、陣列,
使用Object類接收陣列,陣列和Object沒有任何明確的關系,
public class TestDemo4{
public static void main(String args[]){
Object obj = new int []{1,3,4};
int data [] = (int [])obj;//向下轉型
for(int i = 0 ;i < data.length ; i++){
System.out.println(data[i]);
}
}
}
接收介面物件,從介面的定義而言,它是不能去繼承一個父類的,但是由于介面依然屬于參考型別,所以即使沒有繼承類,也可以使用Object接收,
interface Message{}
class MessageImpl implements Message{//定義介面子類
public String toString(){
return "Hello World";
}
}
public class TestDemo5{
public static void main(String args[]){
Message msg = new MessageImpl();//向上轉型
Object obj = msg;//向上轉型
Message temp = (Message) obj;//向下轉型
System.out.println(temp);//toString()
}
}
從代碼上講,以上只能算是一個固定的操作概念,不過從實際來講,因為有了Obejct類的出現,所有的操作就可以達到統一,那么之前的鏈表程式,就應該變得很方便了,所有的資料都使用Object接收,所有的物件比較(洗掉、查找)都可以使用equals(),
3、包裝類
在Java的設計之中,一直倡導一個原則:一切皆物件,這個原則本省有一個漏洞,基本資料型別不是物件,所以這個原則就出現了問題,那么如果說現在這個問題由我們來解決,該如何解決呢?
class MyInt{
private int num;//基本類
public MyInt(int num){
this.num=num;
}
public int intValue(){
return this.num;
}
}
public class TestDemo6{
public static void main(String args[]){
Object obj = new MyInt(10);//子類自動變為Object父類物件
MyInt temp = (MyInt) obj;//向下轉型
int result = temp.intValue();
System.out.println(result*result);
}
}
以上的操作是將基本型別變為了一個物件的形式進行操作了,但是這里面有一個問題:基本數值型資料是可以進行數學運算的,可是以上變為了類的形式,那么肯定無法直接計算了,以上的問題既然我們都想到方法解決,那么Java也一定早已解決,為此它專門提供了八種包裝類:
byte(Byte),short(Short),int(Integer),long(Long),float(Float),double(Double),boolean(Boolean),char(Character);
而這八種包裝類有分為兩大陣營:
? 數值型(Number子類):Byte,Short,Integer(int),Float,Double,Long;
? 物件型(Object子類):Boolean,Character(char),
可是對于Number的子類,就必須觀察出Number類之中定義的方法:byteVlue()、intVlue()、doubleVlue()、shortVlue()、longVlue()、floatVlue(),就是從包裝的類之中取得所包裝的數值,
3.1 裝箱與拆箱
在基本資料型別和包裝類之間的轉化之中分為兩個重要概念:
? 裝箱操作:將基本資料型別變為包裝類,稱為裝箱,包裝類的構造方法,
? 拆箱操作:將包裝類變為基本資料型別,稱為拆箱,Number類中的xxValue()方法,
以int和Integer為例
public class TestDemo{
public static void main(String args[]){
Integer var = new Integer(10);//裝箱
int result = var.intValue();//拆箱
System.out.println(result*result);
}
}
以double和Double為例
public class TestDemo{
public static void main(String args[]){
Double var = new Double(10.0);//裝箱
double result = var.doubleValue();//拆箱
System.out.println(result*result);
}
}
以上的操作實在JDK1.5之前所進行的必須的操作,但是到了JDK1.5之后,Java提供了自動裝箱和自動拆箱的機制,并且包裝類的物件可以自動的進行數學計算了,
自動裝箱與拆箱
public class TestDemo{
public static void main(String args[]){
Integer var = 10;//自動裝箱
int result = var;//自動拆箱
//可以直接利用包裝類進行物件操作
System.out.println(++var*result);//自動進行數學運算
}
}
但是到此為止還有一個小問題,實際上這一問題之前已經見過,
public class TestDemo{
public static void main(String args[]){
Integer x = new Integer(10);//新空間
Integer y = 10;//入池
Integer z = 10;
System.out.println(x==y);//false
System.out.println(x==z);//false
System.out.println(y==z);//ture
System.out.println(x.equals(y));//ture
}
}
使用包裝類的時候還需要考慮equals()和==的區別,
使用int還是Integer?
-
在接收資料的時候,使用的一定都是int,而保存資料的時候一般使用Integer
-
以后撰寫的簡單java類統一不要再去使用基本資料型別,全部換位包裝類
3.2 字串與基本資料型別的轉換
包裝類之中所提供的最大優點在于可以講字串變為制定的基本資料型別,下面列出幾個操作:
? Integer類:public static int parseInt(String s);
? Double類:public static double parseDouble(String s);
? Boolean類:public static boolean parseboolean(String s;
但是character這個包裝類之中,并沒有提供一個類似的parseCharacter(),因為字串String類之中提供了一個charAt()方法,可以取得制定索引的字符,而且一個字符的長度就是一位,
將字串變為int
public class TestDemo{
public static void main(String args[]){
String str = "16";
int result = Integer.parseInt(str);//String ——>int
System.out.println(result*result);
}
}
但是需要提醒的是,在執行這種轉化的操作程序之中,字串字串中的全部內容必須由數字所組成,如果有一位內容不是數字,則在轉化的程序之中講出現如下的錯誤提示:NumbnerFormatException,
將字串變為double
public class TestDemo{
public static void main(String args[]){
String str = "16.";
double result = Double.parsedouble(str);//String ——>int
System.out.println(result*result);
}
}
將字串變為boolean型資料
public class TestDemo{
public static void main(String args[]){
String str = "true";
boolean result = Boolean.parseboolean(str);//String ——>int
System.out.println(result);
}
}
提示:在使用Boolean型包裝類的時候,如果字串之中的內容不是true或者是false,統一都按照false處理,
以上的操作是通過字串變為一些基本型別的資料,但是反過來講,基本資料型別如何變為字串呢?
方式一:任何基本資料型別遇到了String之后都會變為String型資料;
public class TestDemo{
public static void main(String args[]){
int num = 100;
String str = num+"";//int——>String //會產生垃圾
System.out.println(str.length());
}
}
//會有垃圾產生
方式二:利用String方法,public static String valueOf(資料型別 b)
public class BaoZhuangLei{
public static void main(String args[]){
int num = 100;
String str =String.valueOf(num);//int——>String
System.out.println(str.length());
}
}
3.3 包的定義
在Java程式之中的包,主要的目的是可以將不同功能的檔案進行分割,在之前的代碼開發之中,所有的程式都保存在了同一個目錄之中,這樣一來所帶來的問題:如果出現了同名的檔案,那么會發生覆寫問題,因為在同一個目錄之中不允許有重名的檔案,而在不同的目錄下可以有重名檔案,所謂的包實際上指的就是檔案夾,
package cn.mldn.demo;//定義包
public class Hello{
public static void main(String args[]){
System.out.println("Hello World");
}
}
一旦定義完成之后,那么這個類的名字就成了“cn.mldn.demo.Hello”,即這既是完整的類名稱,而在進行程式編譯的時候也需要將*.class檔案保存在包之中,于是為了方便開發,那么也就提供了一個打包的編譯操作,
打包編譯:javac -d . 類.java
-d:表示生成目錄,根據package定義生成
-“.”:再當前目錄下生成*.class
類.java:編譯源程式代碼
這個時候類的名字必須帶上包的名稱,所以執行類的時候:java cn.mldn.demo.Hello,也就是說完整類的名稱就是“包.類”,而在所有的開發之中,沒有包的類是絕對不存在的,只要是程式一定要有包,
3.4 包的匯入
既然使用包可以將一個大型的程式拆分成不同的功能目錄保存,那么這些不同的包之間也一定會存在包的匯入問題,而匯入包在程式之中使用import完成,下面通過一個程式進行演示,
//定義一個Message
package cn.mldn.util;//打包
class Massage{
public String print(){
return "Hello World";
}
}
//定義另外一個類使用Message類
package cn.mldn.text;//打包
import cn.mldn.util.Message;//匯入包
public class Text{
public static void main(String args[]){
Massage msg = new cn.mldn.util.Massage();
System.out.println(msg.print());
}
}
這個時候上面的兩個類應該是按照順序編譯:
? 應該首先編譯Message.java程式:javac –d . Message.java;
? 再次編譯Test.java程式:javac –d . Test.java,但是這個時候出現了一下的錯誤提示:
Text.java:5: 錯誤: Massage在cn.mldn.util中不是公共的; 無法從外部程式包中對其進行
訪問
Massage msg = new cn.mldn.util.Massage();
^
提示:關于public class 和class定義類的區別
? Public class:檔案名和類名稱保持一致,在一個*.java檔案之中只能存在一個public class定義,如果一個類要想被外部包所訪問必須定義為public;
? Class:檔案名稱可以和類名稱不一致,在一個*.java之中可以同事存在多個class定義,并且編譯完成之后會形成多個*.class檔案,使用class定義的類只能夠在一個包中訪問,不同包之間無法訪問,
package cn.mldn.util;//打包
public class Massage{
public String print(){
return "Hello World";
}
}
但是同時也發現了一個問題,現在這些類在編譯的時候要有順序,實在很麻煩,為此在java之中專門提供了一個可以進行自動連編的操作,編譯的時候使用*.java:javac –d . .java,將一個目錄之中所有的.java檔案進行編譯,
? 但是以上的代碼還有一個小問題:程式在進行匯入的時候使用了“包.類”的完整名稱完成的,但是如果在一個程式之中要同時匯入一個包的多個類的時候,那么分開去撰寫實在很麻煩,為此可以使用通配符“*”完成匯入,
package cn.mldn.text;//打包
import cn.mldn.util.*;//匯入包
public class Text{
public static void main(String args[]){
Massage msg = new cn.mldn.util.Massage();
System.out.println(msg.print());
}
}
但是需要注意的是,在java之中使用“”或者是的單獨匯入,其從實際的操作性能上是沒有任何區別的,因為即使使用了也表示匯入所需要的類,不需要的不匯入,
? 可是在匯入包的時候也會遇到一種比較麻煩的問題:會匯入不同包的同名類,例如:對于Message類,現在在兩個包中都有:cn.mldn.util cn.mldn.info
package cn.mldn.text;//打包
import cn.mldn.util.*;//匯入包
import cn.mldn.info.*;//匯入包
public class Text{
public static void main(String args[]){
Message msg = new cn.mldn.util.Message();
System.out.println(msg.print());
}
}
/*
Text.java:6: 錯誤: 對Message的參考不明確, cn.mldn.info中的類 cn.mldn.info.Messag
e和cn.mldn.util中的類 cn.mldn.util.Message都匹配
Message msg = new cn.mldn.util.Message();
^
*/
由于某種需要,同時匯入兩個包,這個時候要使用Message類的時候必須加上類的全名,
package cn.mldn.text;//打包
import cn.mldn.util.*;//匯入包
import cn.mldn.info.*;//匯入包
public class Text{
public static void main(String args[]){
cn.mldn.util.Message msg = new cn.mldn.util.Message();
System.out.println(msg.print());
}
}
4、訪問控制權限
之前學習到的private就屬于一種訪問控制權限,而這種訪問控制權限只是封裝的一部分,再java里面提供有四種訪問控制權限:private、default、protected、public,而這四種訪問控制權限定義如下:
| 范圍 | private | default | protected | public |
|---|---|---|---|---|
| 同一包中的同一類 | √ | √ | √ | √ |
| 同一包中不同類 | √ | √ | √ | |
| 不同包中的子類 | √ | √ | ||
| 不同包中的非子類 | √ |
實際上public永遠都可以訪問,但是對于封裝而言主要使用三個權限:private、default、protected,
觀察protected訪問權限
Info.java
package cn.sxau.demo.a;
public class Info {
//protected權限
protected String str = "www.baidu.com";
}
SubInfo.java
package cn.sxau.demo.a;
import cn.sxau.demo.a.Info;
public class SubInfo extends Info{
public void print(){
System.out.println(super.str);
}
}
TestInfo.java
package cn.sxau.testab;
import cn.sxau.demo.a.SubInfo;
public class TestInfo{
public static void main(String args[]){
new SubInfo().print();
}
}

可以發現SubInfo繼承的子類Info不在同一個包內,但是在同一個子類中,并且可以呼叫其子類,
錯誤代碼
package cn.sxau.testab;
import cn.sxau.demo.a.Info;
public class TestInfo{
public static void main(String args[]){
System.out.println(new Info().str);
}
}
/*
F:\java\javabase\day09>javac -d . TestInfo.java
TestInfo.java:5: 錯誤: str 在 Info 中是 protected 訪問控制
System.out.println(new Info().str);
^
1 個錯誤
*/
原因是str是protected權限,所以在不同類非子類的類中是無法訪問,
對于權限的選擇
- 對于封裝的描述大部分情況下都使用的是private,很少的情況下使用protected,這兩個都叫封裝
- 屬性都是以private,方法都使用public,
封裝性就是指private、protected、default三個權限的使用,
5、jar命令
Jar是一種java給出的壓縮格式檔案,即:可以將*.class檔案以*.jar壓縮包的方式給用戶,這樣方便程式的維護,如果要使用jar的話,可以直接利用JDK給出的jar命令完成,

c:創建一個新的歸檔檔案
f:指定jar的檔案名稱,由用戶制定一個*.jar的檔案名,
v:生成標準的壓縮資訊
Message.java
package cn.sxau.util;//打包
public class Message{
public String print(){
return "hello world";
}
}
- 將Message.java程式進行編譯:javac –d . Message.java,生成包.類;
- 將“包.類”壓縮成my.jar檔案:jar –cvf my.jar cn,出現了一個my.jar包;
此時my.jar就包含了所需要的程式使用類
現在my.jar和MyTest.java處于同一目錄之中,但是發現找不到my.jar之中定義的內容,這是因為在java之中每一個*.jar檔案都屬于一個獨立的CLASSPATH路徑,如果要想使用,必須配置CLASSPATH,
在測驗之前需要在cmd配置SET CLASSPATH=.;F:\java\javabase\day09\my.jar
//定義一個測驗類 呼叫my.jar
package cn.sxau.test;
public class MyTest{
public static void main(String args[]){
cn.sxau.util.Message msg = new cn.sxau.util.Message();
System.out.println(msg.print());
}
}
/*
執行
F:\java\javabase\day09>java cn.sxau.test.MyTest
hello world
*/
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/292479.html
標籤:java
上一篇:爬蟲逆向學習進階路線
