static修饰成员变量:static修饰的成员变量的数据就是共享的数据。
static修饰的成员变量(静态的成员变量)的访问方式:
方式1:可以使用对象访问。 对象.属性名 方式2: 可以使用类名访问。 类名.属性名。 |
注意:
1.非静态的成员变量只能使用对象进行访问,不能使用类名直接访问。
2.千万不要为了方便访问数据而使用static修饰,只有数据真正是需要被共享的时候才使用static修饰。
推荐使用:类名直接访问。
static修饰函数:
静态函数的访问方式: 访问方式1:使用对象访问。 对象.函数名() 访问方式2: 使用类名访问 类名.函数名(); |
1. 静态函数可以使用对象或者类名调用,但是非静态函数只能使用对象进行调用。 2. 静态函数不能出现this与super关键字。 原因:静态函数是可以使用类名直接调用的,而this关键字代表的是所属函数的调用者对象,这时候可能还没有对象的存在。 3. 静态函数可以直接访问静态的成员(成员变量、成员函数),但是不能直接访问非静态的成员。 原因:非静态的成员变量是随着 对象的创建而存在的,静态函数是可以使用类名直接调用的,这时候可能还没有对象存在。 4. 非静态的函数是可以直接访问静态、非静态的成员的。 原因: 非静态函数是需要对象调用的,对象存在的时候静态 数据以及非静态数据都已经存在了,所以可以。 |
什么时候使用static去修饰一个函数呢?
如果一个函数没有直接访到非静态的成员,那么即可使用static修饰。常见的应用在:工具类的方法。
疑惑:静态的函数不能访问非静态的成员?
错误,只要静态函数中存在着的对应的对象那么即可访问。
作用上的区别: 1. 非静态成员变量的作用:描述一类事物的属性。 2. 静态的成员变量作用: 提供了一个共享的数据给所有对象使用。 数量上的区别: 1.非静态的成员变量是随着对象的创建而 存在的,有 多少个对象就有多少份非静态的成员变量数据。 2. 静态的成员变量数据在内存中仅有一份。是所有对象共享的数据。 生命周期的区别: 1. 非静态的成员变量是随着对象的创建而存在,随着对象的消失而消失。 2. 静态的成员变量数据是随着类文件的加载而存在,随着类文件的消失而消失。 |
class Student{ int id; //身份证 String name; //名字
//使用static修饰的数据就是共享的数据,可以被所有的Student对象共享使用,在内存中只有一份。 static Stringcountry = "中国";//国籍
//构造函数 public Student(intid, String name){ this.id =id; this.name =name; } //学习 public void study(){ System.out.println("好好学习,为称为高富帅做准备!!"); } }
class Demo5 { public static void main(String[] args) { Student s1 = new Student(110,"小强"); Student s2 = new Student(119,"小红"); s1.country ="小日本";
System.out.println("身份证:"+s1.id+"名字:"+s1.name+"国籍:"+s1.country); //小日本 System.out.println("身份证:"+s2.id+"名字:"+s2.name+"国籍:"+s2.country); //小日本 } } |
分析:国籍没有static修饰时,运行结果是:(因为此时不是共享的数据)
//身份证:110名字:小强国籍:小日本
//身份证:119名字:小红国籍:中国
解决的问题:保证一个类在内存中的对象唯一性。
比如:多程序读取一个配置文件时,建议配置文件封装成对象。会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中是唯一的。
1. 私有化构造函数。 2. 在本类中创建该类的对象,并且使用一个私有静态的变量指向。 3. 提供有一个公共静态的方法获取本类的对象。 |
1. 私有化构造函数。 2. 声明本类的引用类型变量,但是不创建本类的对象。 3. 提供一个公共静态的方法获取本类的对象,获取对象之前先判断是否已经创建了该类的对象,如果没有创建,那么创建该类的对象并返回,如果已经创建了该类的对象,那么就直接返回即可。 |
推荐使用 : 饿汉式。
因为懒汉式有可能出现线程安全问题,这是时候就无法保证该类在内存中只有一个对象了。
6.3 实现的代码
//懒汉式 class Single2{
//声明本类的引用类型变量,但是不创建本类的对象。 private static Single2 s;
//私有化构造函数 private Single2(){}
//提供有一个公共静态的方法获取本类的对象 public static Single2 getInstance(){ if(s==null){ //没有创建就先创建本类对象 s = new Single2(); } returns; } }
//饿汉式 class Single{
//声明本类的引用类型变量指向本类的对象。 private static Single s = new Single();
//第一步:私有化构造函数 private Single(){}
//提供有一个公共静态的方法获取本类的对象 public static Single getInstance(){ returns; } }
class Demo10 { public static void main(String[] args) { Single2 s1 = Single2.getInstance(); Single2 s2 = Single2.getInstance(); System.out.println("两个对象是同一个吗?"+ (s1==s2));//true } } |
继承的格式:
class 类名1 extends类名2{ } |
继承的特点
1:描述类和类之间的关系 2:降低类和类之间的重复代码 3:降低对象和对象之间的代码重复使用静态变量 4:降低类和类之间的代码重复使用就继承 |
继承的好处
继承的出现提高了代码的复用性。 继承的出现让类与类之间产生了关系,提供了多态的前提。 |
继承要注意的细节:
1. 千万不要为了减少重复代码而去继承,只有两种事物真正存在着继承关系的时候才去继承。 2. 父类私有的成员不能被继承。 3. 父类的构造函数不能被继承。 4. 创建子类对象时,会先调用父类的构造函数。 |
疑惑:为什么创建子类对象的时候会先调用父类的构造函数呢,这样子做的意义在那?
意义就是:初始化从父类继承下来的属性。
super关键字代表的是父类空间的引用。
1. 子父类存在着同名的成员时,在子类默认是访问子类的成员,可以通过super关键字指定访问父类的成员。 2. 创建子类对象时,默认是会先调用父类无参的构造方法,可以通过super关键字指定调用父类其他的构造方法。 3、主要存在于子类的方法中,用于指向子类对象中父类对象 |
1. 如果子类的构造函数没有指定调用父类构造函数,那么java编译器会在子类的构造函数中加上super(); 2. super 调用父类的构造函数的时候必须是在构造函数中的第一个语句。 3. this 与super关键字调用构造函数时,不能同时出现在一个构造函数中,因为两个都需要在第一个语句。 |
1. super关键字只能在继承的关系下才能使用,this关键字不需要继承照样可以使用。 2. super关键字代表的是父类空间的引用。this代表的是所属函数的调用者对象。 3. super在子类的构造函数中是调用父类的构造函数,this关键字是构造函数中是调用本类的构造函数 4. super可以用作区分同名的子父类成员,可以指定访问父类的成员。 this关键字是用作区分同名的成员变量与局部变量的。 |
super思考
如果开发者自定义了一个类,没有显示的进行类的继承,那么该类中成员函数是否可以使用super关健健字?可以使用,继承了Object类,Object类是所有类的父类。
class Demo7 { public void print(){ System.out.println(super.toString());//继承了Object类 } public static void main(String[] args){ new Demo7().print(); System.out.println(); } } |
小知识点
子类对象查找属性或方法时的顺序:
1:原则:就近原则。
如果子类的对象调用方法,默认先使用this进行查找,如果当前对象没有找到属性或方法,找当前对象中维护的super关键字指向的对象,如果还没有找到编译报错,找到直接调用。
重载和重写的不同
1:重载(overload):
1:前提: 所有的重载函数必须在同一个类中
2:特点:
函数名相同,参数列表不同,与其他的无关(访问控制符、返回值类型)
3:不同:
个数不同 、 顺序不同、 类型不同
2:重写(override):
1:前提:继承
2:特点:
函数名必须相同、参数列表必须相同。
子类的返回值类型要等于或者小于父类的返回值
作用: 判断一个对象是否属于指定的类别。
使用前提: 判断的对象与指定的类别必须要存在着继承或者是实现的关系。
instanceof 使用格式:
对象instanceof 类
//动物类 class Animal{ String name;//名字 String color;//颜色
//构造方法 public Animal(Stringname,String color){ this.name =name; this.color =color; } }
//狗 是属于动物中的一种 class Dog extends Animal{ public Dog(Stringname ,String color){ super(name,color); }
//咬人 public void bite(){ System.out.println(name+"狠狠的咬人!!"); } }
//鱼也是属于动物中的一种 class Fish extends Animal { //构造方法。 public Fish(Stringname,String color){ super(name,color); } public void swing(){ System.out.println(name+"在水里游...."); } }
class Demo8 { public static void main(String[] args) { Animal a = new Animal("动物","黑色"); Dog d = new Dog("哈士奇","白色"); System.out.println("动物都属于狗类吗?"+(ainstanceof Dog)); System.out.println("狗是属于动物类别吗?"+(dinstanceof Animal)); // 判断对象是否属于狗类型,如果是返回true,否则返回false. } } |
作用:增强数据的安全性。
1. final修饰一个基本类型的变量时,该变量不能重新赋值。
2. final 修饰一个引用类型变量时,该变量不能重新指向新的对象。
3. fianl 修饰一个方法的时候,该方法不能被重写。
4. fianl 修饰一个类的时候,该类不能被继承。为最终的类
常量的修饰符: public static final
常量的命名规范:全部字母大写,单词与单词之间使用下划线分隔。
final class Circle{ //狗剩 public static final double PI = 3.14 ; //PI的值应该是固定的。 //半径 int r; public Circle(intr){ this.r =r; }
public Circle(){} //获取面积 public final void getArea(){ System.out.println("面积是:"+PI*r*r); } }
class Demo extends Circle //final 修饰的类不能被继承 { public static void main(String[] args) { //创建一个圆形对象。 final Circlec = new Circle(4); test(c); /* c.PI = 0.0; // 狗娃 c.getArea(); //System.out.println("Hello World!"); */ }
public static void test(Circle c){ //让c变量重新指向一个新的对象。 c = new Circle(5); } } |
描述一类事物的时候,发现该类事物目前确实存在着某种行为,但是目前这种行为是不具体的,那么这时候我们可以把这种行为描述抽象的行为,只抽取这种行为功能的声明,而不实现该功能行为,这时候我们可以使用抽象类描述。
抽象类的好处:强制子类去实现指定的方法。
抽象类主要为了提高代码的复用性,让子类继承来使用。
1. 如果一个类有抽象的方法,那么该类就必须使用abstract修饰。 2. 非抽象类继承抽象类的时候,必须要把抽象类的所有抽象方法实现。(抽象方法具体化) 3. 抽象类可以存在非抽象方法与抽象方法的。 4. 抽象类可以不存在抽象的方法。 5. 抽象类不能创建对象。 疑问:为什么抽象类不能创建对象呢? 抽象类如果创建了对象,抽象类就调用对应的方法了,抽象类是具有抽象方法的,如果调用了抽象的方法(抽象方法内没有具体功能),这样子是没有意义的。 6. 抽象类是存在构造函数的。 疑问:抽象类不能创建对象,那么存在构造函数的意义何在呢? 抽象的构造函数是提供给其子类使用的,因为需要初始化从父类继承下来的属性数据。
|
final与abstract不能共存: final:它的作用 修饰类代表不可以继承 修饰方法不可重写 abstract修饰类就是用来被继承的,修饰方法就是用来被重写的。 Static static修饰的方法可以用类名调用, 对于abstract修饰的方法没有具体的方法实现,所有不能直接调用,也就是说不可以与static共存。 private private修饰的只能在本类中使用, abstract方法是用来被子类进行重写的,有矛盾所有不能共存. |
//动物类 abstract class Animal { String name ; String color; //构造函数 public Animal(Stringname ,String color){ this.name =name; this.color =color; }
//跑 抽象的方法 public abstract final void run(); //抽象的行为。 加final修饰后的方法不能被重写 //非抽象的方法。 public void eat(){ System.out.println("吃粮食.."); } }
//狗 非抽象类 class Dog extends Animal{
//构造函数 public Dog(Stringname,String color){ super(name,color); } public void run(){ //run方法被final修饰 System.out.println(name+"四条腿跑得很快..."); } }
//鱼 非抽象类 抽象类 class Fish extends Animal{
public Fish(Stringname,String color){ super(name,color); }
public void run(){ //run方法被final修饰 System.out.println(name+"摇摇尾巴游啊游!!..."); } }
class Demo10 { public static void main(String[] args) { /* //System.out.println("Hello World!"); //创建一个狗对象 Dog dog = new Dog("牧羊犬","棕色"); dog.run();
//创建一个鱼对象 Fish f = new Fish("锦鲤","金色"); f.run(); */
//创建一个抽象类的对象。 //Animal a = new Animal("动物","黑色"); //a.run(); } } |