標識符
什么是標識符
就是程序員在定義java程序時,自定義的一些名字,例如helloworld 程序里關鍵字class 后跟的Demo,就是我們定義的類名。類名就屬于標識符的一種。標識符除了應用在類名上,還可以用在變量、函數名、包名上-
標識符必須遵循以下規則
- 標識符由26個英文字符大小寫(azAZ)、數字(0~9)、下劃線(_)和美元符號($)組成。
- 不能以數字開頭,不能是關鍵字
- 嚴格區分大小寫
- 標識符的可以為任意長度
this關鍵字
- this關鍵字代表了所屬函數的調用者對象
- this關鍵字作用
- 如果存在同名成員變量與局部變量時, 在方法內部默認是訪問局部變量的數據, 可以通過this關鍵字指定訪問成員變量的數據
- 在一個構造函數中可以調用另外一個構造函數初始化對象
- this關鍵字調用其他的構造函數要注意的事項
- this關鍵字調用其他的構造函數時, this關鍵字必須要位于構造函數中的第一個語句
- this關鍵字在構造函數中不能出現相互調用的情況, 因為是一個死循環
- this關鍵字要注意事項
- 存在同名的成員變量與局部變量時, 在方法的內部訪問的是局部變量(java 采取的是“就近原則”的機制訪問的)
- 如果在一個方法中訪問了一個變量, 該變量只存在成員變量的情況下, 那么java編譯器會在該變量的前面添加this關鍵字
- this關鍵字調用其他的構造函數要注意的事項:
- this關鍵字調用其他的構造函數時, this關鍵字必須要位于構造函數中的第一個語句
- this關鍵字在構造函數中不能出現相互調用 的情況, 因為是一個死循環
class Student{
int id; //身份證
String name; //名字
//目前情況:存在同名 的成員 變量與局部變量,在方法內部默認是使用局部變量的。
public Student(int id,String name){ //一個函數的形式參數也是屬于局部變量。
this(name); //調用了本類的一個參數的構造方法
//this(); //調用了本類無參的構造方法。
this.id = id; // this.id = id 局部變量的id給成員變量的id賦值
System.out.println("兩個參數的構造方法被調用了...");
}
public Student(){
System.out.println("無參的構造方法被調用了...");
}
public Student(String name){
this.name = name;
System.out.println("一個參數的構造方法被調用了...");
}
}
class Demo
{
public static void main(String[] args)
{
Student s = new Student(110, "鐵蛋");
System.out.println("編號:"+ s.id +" 名字:" + s.name);
/*
Student s2 = new Student("金胖子");
System.out.println("名字:" + s2.name);
*/
}
}
static(靜態)
-
static(靜態\修飾符) : 靜態的成員變量只會在數據共享區中維護一份,而非靜態成員變量的數據會在每個對象中都維護一份的
- static修飾成員變量 : 如果有數據需要被共享給所有對象使用時, 那么就可以使用static修飾
- 靜態成員變量的訪問方式:
- 方式1 : 可以使用對象進行訪問
格式 : 對象.變量名
- 方式二 : 可以使用類名進行訪問
格式 : 類名.變量名 - 注意 :
1. 非靜態的成員變量只能使用對象進行訪問,不能使用類名進行訪問。
2. 千萬不要為了方便訪問數據而使用static修飾成員變量,只有成員變量的數據是真正需要被共享的時候才使用static修飾。 - static修飾成員變量的應用場景 : 如果一個數據需要被所有對象共享使用的時候,這時候即可好實用static修飾
- static修飾成員函數 : (靜態函數)
-
訪問方式:
方式一:可以使用對象進行訪問。
對象.靜態的函數名()
方式二:可以使用類名進行訪問。
類名.靜態函數名字。推薦使用是類名直接訪問靜態的成員。
-
靜態的成員變量與非靜態的成員變量的區別:
- 作用上的區別:
1. 靜態的成員變量的作用共享一個 數據給所有的對象使用。
2. 非 靜態的成員變量的作用是描述一類事物的公共屬性。 - 數量與存儲位置上的區別:
1. 靜態成員變量是存儲方法 區內存中,而且只會存在一份數據。
2. 非靜態的成員變量是存儲在堆內存中,有n個對象就有n份數據。 - 生命周期的區別:
1. 靜態的成員變量數據是隨著類的加載而存在, 隨著類文件的消失而消失
2.非靜態的成員數據是隨著對象的創建而存在, 隨著對象被垃圾回收器回收而消失。
- 作用上的區別:
-
靜態函數要注意的事項:
- 靜態函數是可以調用類名或者對象進行調用的,而非靜態函數只能使用對象進行調用。
- 靜態的函數可以直接訪問靜態的成員,但是不能直接訪問非靜態的成員。
原因 : 靜態函數是可以使用類名直接調用的, 這時候可能還沒有存在對象, 而非靜態的成員數據是隨著對象的存在而存在的 - 非靜態的函數是可以直接訪問靜態與非靜態的成員
原因 : 非靜態函數只能由對象調用, 當對象存在的時候, 靜態數據老早就已經存在了, 而非靜態數據也隨著對象的創建而存在了 - 靜態函數不能出現this或者super關鍵字。
原因 : 因為靜態的函數是可以使用類名調用的, 一旦使用類名調用這時候不存在對象, 而this關鍵字是代表了一個函數 的調用者對象, 這時候產生了沖突
靜態的數據的生命周期:靜態的成員變量數據是優先于對象存在的
static什么時候修飾一個函數?
如果一個函數沒有直接訪問到非靜態的成員時,那么就可以使用static修飾了(一般用于工具類型的方法)靜態函數不能訪問非靜態的成員?
靜態函數只要存在有對象, 那么也可以訪問非靜態的數據, 只是不能直接訪問而已
super關鍵字
super關鍵字代表了父類空間的引用
-
super關鍵字的作用 :
- 子父類存在著同名的成員時,在子類中默認是訪問子類的成員,可以通過super關鍵字指定訪問父類的成員
- 創建子類對象時,默認會先調用父類無參的構造方法,可以通過super關鍵字指定調用父類的構造方法
-
super關鍵字調用父類構造方法要注意的事項:
- 如果在子類的構造方法上沒有指定調用父類的構造方法,那么java編譯器會在子類的構造方法上面加上super()語句
- super關鍵字調用父類的構造函數時,該語句必須要是子類構造函數中的第一個語句
- super與this關鍵字不能同時出現在同一個構造函數中調用其他的構造函數。因為兩個語句都需要第一個語句
-
super關鍵字與this關鍵字的區別:
- 代表的事物不一致
1. super關鍵字代表的是父類空間的引用
2. this關鍵字代表的是所屬函數的調用者對象 - 使用前提不一致
1. super關鍵字必須要有繼承關系才能使用
2. this關鍵字不需要存在繼承關系也可使用 - 調用構造函數的區別 :
1. super關鍵字是調用父類的構造函數
2. this關鍵字是調用本類的構造函數
- 代表的事物不一致
instanceof 關鍵字
- instanceof關鍵字的作用:判斷一個對象是否屬于指定的類別。
- instanceof關鍵字的使用前提:判斷的對象與指定的類別必須要存在繼承或者實現的關系(學習接口的時候就會理解)
- instanceof關鍵字的使用格式:
對象 instanceof 類別 - instanceof關鍵字的作用:一般做強制類型轉換之前都會使用該關鍵字先判斷一下,然后在進行轉換
final(最終、修飾符)
- final關鍵字的用法:
- final關鍵字修飾一個基本類型的變量時,該變量不能重新賦值,第一次的值為最終的
- fianl關鍵字修飾一個引用類型變量時,該變量不能重新指向新的對象
- final關鍵字修飾一個函數的時候,該函數不能被重寫
- final關鍵字修飾一個類的時候,該類不能被繼承
- 常量 的修飾符一般為: public static final
//圓形
class Circle{
double r; //半徑
public static final double pi = 3.14; //固定不變的
public Circle(double r){
this.r = r;
}
//計算面積
public final void getArea(){
System.out.println("圓形的面積是:"+r*r*pi);
}
}
class Demo2 extends Circle
{
public Demo2(double r){
super(r);
}
public static void main(String[] args)
{
/*
final Circle c = new Circle(4.0);
test(c);
*/
Demo2 c = new Demo2(4.0);
c.getArea();
}
public static void test(Circle c){
c = new Circle(5.0); //c變量又重新指向了新的對象。
c.getArea();
}
}
抽象類 : abstract
-
抽象類的應用場景:
- 我們在描述一類事物的時候,發現該種事物確實存在著某種行為, 但是這種行為目前是不具體的,那么我們可以抽取這種行為 的聲明,但是不去實現該種行為,這時候這種行為我們稱作為抽象的行為,我們就需要使用抽象類
- 目前存在的問題:
- 動物類的run方法描述的不正確
- 沒有強制要子類一定要重寫run方法
抽象類的好處: 強制要求子類一定要實現指定的方法。
-
抽象類要注意的細節 :
- 如果一個函數沒有方法體, 那么該函數必須要使用abstract修飾把函數修飾成抽象的函數
- 如果一個類出現了抽象的函數,那么該類也必須使用abstract修飾
- 如果一個非抽象類繼承了抽象類, 那么必須要把抽象類的所有抽象方法全部實現
- 抽象類可以存在非抽象方法, 也可以存在抽象的方法
- 抽象類可以不存在抽象方法的
- 抽象類是不能創建對象的
疑問:為什么抽象類不能創建對象呢?
因為抽象類是存在抽象方法的,如果能讓抽象類創建對象的話,那么使用抽象的對象調用抽象方法是沒有任何意義的 - 抽象類是存在構造函數的,其構造函數是提供給子類創建對象的時候初始化父類的屬性的
-
abstract不能與以下關鍵字共同修飾一個方法:
- abstract不能與private共同修飾一個方法
- abstract 不能與static共同修飾一個方法
- abstract 不能與final共同修飾一個方法
//動物類--->抽象類
abstract class Animal{
String name;
String color;
public Animal(String name,String color){
this.name = name;
this.color = color;
}
//非抽象的方法
public void eat(){
System.out.println(name+"吃糧食");
}
//移動...(該函數沒有方法體, 所以必須使用abstract修飾該函數)
public abstract void run();
}
//狗 是屬于動物中一種
class Dog extends Animal{
public Dog(String name,String color){
super(name,color);
}
public void run(){
System.out.println(name+"四條腿跑得很快...");
}
}
//魚 是屬于動物中一種
class Fish extends Animal{
public Fish(String name,String color){
super(name,color);
}
public void run(){
System.out.println(name+"搖搖尾巴游啊游!");
}
}
class Demo{
public static void main(String[] args)
{
/*
Dog d = new Dog("牧羊犬","棕色");
d.run();
//創建一個魚對象
Fish f = new Fish("錦鯉","金黃色");
f.run();
*/
Animal a = new Animal();
}
}
- 常量的命名規范:全部字母大寫,單詞與單詞之間使用下劃線分隔
配置文件類
- Properties(配置文件類): 主要用于生產配置文件與讀取配置文件的信息。
- Properties要注意的細節:
- 如果配置文件的信息一旦使用了中文,那么在使用store方法生成配置文件的時候只能使用字符流解決,如果使用字節流生成配置文件的話,默認使用的是iso8859-1碼表進行編碼存儲,這時候會出現亂碼。
- 如果Properties中的內容發生了變化,一定要重新使用Properties生成配置文件,否則配置文件信息不會發生變化。
public class Demo{
public static void main(String[] args) throws IOException {
creatProperties();
// readProperties();
}
//讀取配置文件愛你的信息
public static void readProperties() throws IOException{
//創建Properties對象
Properties properties = new Properties();
//加載配置文件信息到Properties中
properties.load(new FileReader("F:\\persons.properties"));
//遍歷
Set<Entry<Object, Object>> entrys = properties.entrySet();
for(Entry<Object, Object> entry :entrys){
System.out.println("鍵:"+ entry.getKey() +" 值:"+ entry.getValue());
}
//修改狗娃的密碼
//把修改后的Properties再生成一個配置文件
properties.setProperty("狗娃", "007");
properties.store(new FileWriter("F:\\persons.properties"), "hehe");
}
//保存配置文件文件的信息
public static void creatProperties() throws IOException{
//創建Properties
Properties properties = new Properties();
properties.setProperty("狗娃", "123");
properties.setProperty("狗剩","234");
properties.setProperty("鐵蛋","345");
// 遍歷Properties
/*Set<Entry<Object, Object>> entrys = properties.entrySet();
for(Entry<Object, Object> entry :entrys){
System.out.println("鍵:"+ entry.getKey() +" 值:"+ entry.getValue());
}*/
//使用Properties生產配置文件。
//properties.store(new FileOutputStream("F:\\persons.properties"), "haha"); //第一個參數是一個輸出流對象,第二參數是使用一個字符串描述這個配置文件的信息。
properties.store(new FileWriter("F:\\persons.properties"), "hehe");
}
}
需求: 使用properties實現本軟件只能運行三次,超過了三次之后就提示購買正版,退jvm.
public class Demo1 {
public static void main(String[] args) throws IOException {
File file = new File("F:\\count.properties");
if(!file.exists()){
//如果配置文件不存在,則創建該配置文件
file.createNewFile();
}
//創建Properties對象。
Properties properties = new Properties();
//把配置文件的信息加載到properties中
properties.load(new FileInputStream(file));
FileOutputStream fileOutputStream = new FileOutputStream(file);
int count = 0; //定義該變量是用于保存軟件的運行次數的。
//讀取配置文件的運行次數
String value = properties.getProperty("count");
if(value!=null){
count = Integer.parseInt(value);
}
//判斷使用的次數是否已經達到了三次,
if(count==3){
System.out.println("你已經超出了試用次數,請購買正版軟件!!");
System.exit(0);
}
count++;
System.out.println("你已經使用了本軟件第"+count+"次");
properties.setProperty("count",count+"");
//使用Properties生成一個配置文件
properties.store(fileOutputStream,"runtime");
}
}