标识符
什么是标识符
就是程序员在定义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");
}
}