一、static关键字
1.static 修饰属性和方法
当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过 new 关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。
我们有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份。
例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。
/*** static关键字的使用* 1.static 静态的* 2.static 可以用来修饰 属性、方法、代码块、内部类* 3.使用 static 修饰属性:静态变量(或类变量)。* 3.1 属性:是否使用 static 修饰,又分为:静态属性 VS 非静态属性(实例变量)* 实例变量:我们创建了类的多个对象,每个对象都独立的拥有了一套类中的非静态属性。* 当修改其中一个非静态属性时,不会导致其他对象中同样的属性值的修饰。* 静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过静态变量去修改某一个变量时,* 会导致其他对象调用此静态变量时,是修改过的。* 3.2 static 修饰属性的其他说明:* ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用。* ② 静态变量的加载要早于对象的创建。* ③ 由于类只会加载一次,则静态变量在内存中也只会存在一次。存在方法区的静态域中。* 4.静态属性举例:System.out、Math.PI* 5.使用 static 修饰方法:静态方法* ① 随着类的加载而加载,可以通过"类.静态方法"的方式调用* ② 静态方法 非静态方法* 类 yes no* 对象 yes yes* ③ 静态方法中,只能调用静态的方法或属性* 非静态的方法中,可以调用所有的方法或属性* 6.static 注意点:* 6.1 在静态的方法内,不能使用 this 关键字、super 关键字* 6.2 关于静态属性和静态方法的使用,大家从生命周期的角度去理解。* 7.开发中,如何确定一个属性是否需要声明 static 的?* > 属性是可以被多个对象所共享的,不会随着对象的不同而不同的。* > 类中的常量也常常声明为 static** 开发中,如何确定一个方法是否要声明为 static 的?* > 操作静态属性的方法,通常设置为 static 的* > 工具类中的方法,习惯上声明为 static 的。比如:Math、Arrays、Collections*/public class StaticTest{public static void main(String[] args) {//静态变量加载随着类的加载而加载,早于对象的创建Chinese.nation = "中国";//可以提前调用//实例化Chinese c1 = new Chinese();c1.name = "嘉然";c1.age = 3;Chinese c2 = new Chinese();c2.name = "乃琳";c2.age = 18;//修改c1的nationc1.nation = "CHN";//这种方法其实有点问题,正规方法为:Chinese nation = "CHN"; 此处仅为好说明问题//输出c2的nationSystem.out.println(c2.nation);//也为CHN,有点全局变量的味儿~//非静态方法只能用对象c1.eat();//静态方法可以用类来调用Chinese.show();}}class Chinese{String name;int age;static String nation;//非静态方法public void eat(){System.out.println("中国人吃中餐");}//静态方法public static void show(){System.out.println("我是中国人");}}
2.类变量 vs 实例变量内存解析
3. 自定义数组工具类的优化
3.二.11的老代码,可以转换成static
/*** Test*/public class Test {public static void main(String[] args) {int[] arr = new int[]{1,2,3};//ArrayUtil arraytool = new ArrayUtil(); 换成是static没必要new对象了arraytool.getReversal(arr);}}class ArrayUtil{public static void getMax(int[] arr){// 求数组的最大值int max = arr[0];for(int i = 1;i < arr.length;i++){if(max < arr[i]){max = arr[i];}}System.out.println(max);}public void static getMin(int[] arr){// 求数组的最小值int min = arr[0];for(int i = 1;i < arr.length;i++){if(min > arr[i]){min = arr[i];}}System.out.println(min);}public void static getSum(int[] arr){// 求数组的总和int sum = arr[0];for(int i = 1;i < arr.length;i++){sum += arr[i];}System.out.println(sum);}public void static getAver(int[] arr){// 求平均值int sum = arr[0];for(int i = 1;i < arr.length;i++){sum += arr[i];}int aver = sum / arr.length;System.out.println(aver);}public void static getReversal(int[] arr){// 反转数组for(int i = 0, j = arr.length-1;i < j;i++, j--){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}for(int i = 0;i < arr.length;i++){System.out.println(arr[i]);}}public int[] static getCopy(int[] arr){// 创建备份数组,且长度相等int[] beifen = new int[arr.length];// 遍历原数组并赋给备份数组for(int i = 0;i < arr.length;i++){beifen[i] = arr[i];}// 遍历备份数组for(int i = 0;i < beifen.length;i++){System.out.print(beifen[i]);}return beifen;}public void static getOrder(int[] arr){// 数组排序for(int i = 0;i < arr.length - 1;i++){for(int j = 0;j < arr.length - 1 -i;j++){if(arr[j] > arr[j+1]){int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}for(int i = 0;i < arr.length;i++){System.out.println(arr[i]);}}public void static getSerch(int[] arr, int desitination){// 查找指定元素for(int i = 0;i < arr.length;i++){if(desitination == arr[i]){System.out.println("找到了索引为" + i);}}}}
4.static 应用举例
//static 关键字的应用public class CircleTest {public static void main(String[] args) {Circle c1 = new Circle();Circle c2 = new Circle();Circle c3 = new Circle();System.out.println("c1 的 ID:" + c1.getId());System.out.println("c2 的 ID:" + c2.getId());System.out.println("c3 的 ID:" + c3.getId());System.out.println("创建圆的个数: " + Circle.getTotal());}}class Circle{private double radius;private int id; //需要自动赋值public Circle(){id = init++;total++;}public Circle(double radius){this();//或// id = init++;// total++;this.radius = radius;}private static int total;//记录创建圆的个数private static int init = 1001;//static 声明的属性被所有对象所共享public double findArea(){return 3.14 * radius * radius;}public double getRadius() {return radius;}public void setRadius(double radius) {this.radius = radius;}public int getId() {return id;}public static int getTotal() {return total;}}
5.设计模式和单例设计模式
二、main()方法(了解)
1.理解main()方法
/*** 1.main()方法作为程序的入口* 2.main()方法也是一个普通的静态方法* 3.main()方法也可以做为和控制台交互的方式* 具体为1.编译:javac demo.java 2.运行:java demo 参数1 参数2 ... 参数n*/public class MainTest {public static void main(String[] args) {//静态方法可以直接调用Main.main(new String[100]);}}class Main{public static void main(String[] args) {for(int i = 0;i < 100;i++){args[i] = "arg" + i;System.out.println(args[i]);}}}
三、类的成员之代码块
1.类中代码块结构的使用
/*** 类的成员之四:代码块(或初始化块)* 1.代码块的作用:初始化类和对象* 2.代码块只能使用static修饰(也就分为静态代码块和非静态代码块)* 3.静态代码块:* >内部可以有输出语句* >随着类的加载而执行,而且只执行一次* >静态代码块只能调用静态属性 静态方法* >作用:初始化类的信息* 4.非静态代码块* >内部可以有输出语句* >每创建一个对象就执行一次* >非静态代码块可以调用静态属性 静态方法 非静态属性 非静态方法* >作用:在创建对象时可以对对象进行初始化* 5.静态代码块始终优先于非静态执行*/public class BlockTest {public static void main(String[] args) {Person p = new Person();//随着对象加载非static代码块执行了p.eat();}}class Person{//属性String name;int age;static String description = "我是一个人";//构造器public Person(){}public Person(String name,int age){this.name = name;this.age = age;}//static代码块static{System.out.println("你好,夹心糖的静态代码块");//只能调用静态的description = "我是一个人类";Person.info();}//非static代码块{System.out.println("你好,夹心糖的非静态代码块");description = "我是一个人类";Person.info();//非静态的属性,方法也能调name = "Tom";age = 12;this.eat();}//方法public void eat(){System.out.println("吃饭");}@Overridepublic String toString() {return "Person[name=" + name + ",age=" + age + "]";}//静态方法public static void info(){System.out.println("我是人类");}}
2.代码块举例
//总结:由父类到子类,静态先行class Root{static{System.out.println("Root 的静态初始化块");}{System.out.println("Root 的普通初始化块");}public Root(){System.out.println("Root 的无参数的构造器");}}class Mid extends Root{static{System.out.println("Mid 的静态初始化块");}{System.out.println("Mid 的普通初始化块");}public Mid(){System.out.println("Mid 的无参数的构造器");}public Mid(String msg){//通过 this 调用同一类中重载的构造器this();System.out.println("Mid 的带参数构造器,其参数值:"+ msg);}}class Leaf extends Mid{static{System.out.println("Leaf 的静态初始化块");}{System.out.println("Leaf 的普通初始化块");}public Leaf(){//通过 super 调用父类中有一个字符串参数的构造器super("尚硅谷");System.out.println("Leaf 的构造器");}}public class LeafTest{public static void main(String[] args){new Leaf();//new Leaf();}}
四、final关键字
1.final关键字的使用及注意
/*** 1.final可以修饰 类 变量 方法* 2.final修饰类不能被继承。比如:String类、System类、StringBuffer类* 3.final修饰方法表示方法不会被重写* 4.final修饰变量:此时“变量”变成常量了.显式初始化、代码块中初始化、构造器中初始化* 5.final修饰形参的时候也传入值也会变成常量* 6.static final : 修饰一个全局变量*/public class FinalTest {final int width = 10;public void doWidth(){//错误的,常量无法被操作width+=5;}public void show(final int num){//传入参数用finalnum+=5;}public static void main(String[] args) {int num = 10;num = num + 5;}}//final修饰类后,无法被其他类继承final class A{}//错误的,final修饰类后,无法被其他类继承class B extends A{}class AA{//final修饰方法后不能被重写public final void show(){}}class BB extends AA{//错误的,final修饰方法后不能被重写public void show(){}}
六、抽象类与抽象方法
1.抽象类与抽象方法的使用
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
package com.test.java;/** abstract关键字的使用* 1.abstract:抽象的* 2.abstract可以修饰类、方法* 3.abstract修饰类:* >此类就不能实例化* >抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对象实例化的全过程)* >开发中,都会提供抽象类的子类,让子类对象实例化,完成父类相关的操作* 4.abstract修饰方法:抽象方法* >抽象方法只有方法的声明,没有方法体* >包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。* >若子类重写了父类中的所有的抽象方法后,此子类方可实例化*/public class Hello {public static void main(String[] args) {//一旦Person类抽象了,就不可实例化// Person p1 = new Person();// p1.eat();}}abstract class Person{String name;int age;public Person(){}public Person(String name,int age){this.name = name;this.age = age;}//不是抽象方法// public void eat(){// System.out.println("人吃饭");// }//抽象方法,分号结尾public abstract void eat();public void sleep(){System.out.println("人睡觉");}}class Student extends Person{public Student(String name,int age){super(name, age);}//子类必须重写父类的抽象方法,才可实例化public void eat(){System.out.println("学生吃健康的");}}

/* Java 允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子类提 供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。* Vehicle 是一个抽象类,有两个抽象方法。* 注意:抽象类不能实例化 new Vihicle()是非法的*/public abstract class Vehicle{public abstract double calcFuelEfficiency();//计算燃料效率的抽象方法public abstract double calcTripDistance();//计算行驶距离的抽象方法}public class Truck extends Vehicle{public double calcFuelEfficiency(){//写出计算卡车的燃料效率的具体方法}public double calcTripDistance(){//写出计算卡车行驶距离的具体方法}}public class RiverBarge extends Vehicle{public double calcFuelEfficiency() {//写出计算驳船的燃料效率的具体方法}public double calcTripDistance( ) {//写出计算驳船行驶距离的具体方法}}
2.练习
package com.test.java;/** 编写一个 Employee 类,声明为抽象类,* 包含如下三个属性:name,id,salary。* 提供必要的构造器和抽象方法:work()。* 对于 Manager 类来说,他既是员工,还具有奖金(bonus)的属性。* 请使用继承的思想,设计 CommonEmployee 类和 Manager 类,* 要求类中提供必要的方法进行属性访问。*/public abstract class Employee {private String name;private int id;private double salary;public Employee(){}public Employee(String name,int id,double salary){this.name = name;this.id = id;this.salary = salary;}public abstract void work();}
/** 对于 Manager 类来说,他既是员工,还具有奖金(bonus)的属性。**/public class Manager extends Employee{private double bonus; //奖金public Manager(double bonus) {super();this.bonus = bonus;}public Manager(String name, int id, double salary, double bonus) {super(name, id, salary);this.bonus = bonus;}@Overridepublic void work() {System.out.println("管理员工,提高公司运行效率。");}}
public class CommonEmployee extends Employee {@Overridepublic void work() {System.out.println("员工在一线车间生产产品。");}}
/** 请使用继承的思想,设计 CommonEmployee 类和 Manager 类,*/public class EmployeeTest {public static void main(String[] args) {Employee manager = new Manager("库克",1001,5000,50000);manager.work();CommonEmployee commonEmployee = new CommonEmployee();commonEmployee.work();}}
3.创建抽象类的匿名子类对象
/** 抽象类的匿名子类**/public class PersonTest {public static void main(String[] args) {method(new Student()); //匿名对象Worker worker = new Worker();method1(worker); //非匿名的类非匿名的对象method1(new Worker()); //非匿名的类匿名的对象System.out.println("*********************");//创建了一个匿名子类的对象:pPerson p = new Person(){@Overridepublic void eat() {System.out.println("吃东西");}@Overridepublic void breath() {System.out.println("呼吸空气");}};method1(p);System.out.println("**********************");//创建匿名子类的匿名对象method1(new Person(){@Overridepublic void eat() {System.out.println("吃零食");}@Overridepublic void breath() {System.out.println("云南的空气");}});}public static void method1(Person p){p.eat();p.walk();}public static void method(Student s){}}class Worker extends Person{@Overridepublic void eat() {}@Overridepublic void breath() {}}
4.模板方法设计模式
/** 抽象类的应用:模板方法的设计模式*/public class TemplateTest {public static void main(String[] args) {SubTemlate t = new SubTemlate();t.sendTime();}}abstract class Template{//计算某段代码执行所需花费的时间public void sendTime(){long start = System.currentTimeMillis();code(); //不确定部分,易变的部分long end = System.currentTimeMillis();System.out.println("花费的时间为:" + (end - start));}public abstract void code();}class SubTemlate extends Template{@Overridepublic void code() {for(int i = 2;i <= 1000;i++){boolean isFlag = true;for(int j = 2;j <= Math.sqrt(i);j++){if(i % j == 0){isFlag = false;break;}}if(isFlag){System.out.println(i);}}}}
七、接口
1.接口的理解
2.接口的定义、使用、多实现、继承
package com.test.java;/** 接口的使用* 1.接口使用interface来定义* 2.Java中,接口是和类并列的结构* 3.JDK7以前:只能定义全局常量和抽象方法* >全局常量:public static final* >抽象方法:public abstract* 4.JDK8增加了静态方法和默认方法* 5.接口通过让类去实现(implements)的方式来使用* 6.Java可以实现多个接口* 格式:class AA extend BB implements CC,DD,EE*/public class InterfaceTest {public static void main(String[] args) {System.out.println(Flyable.MAX_SPEED);Plane p = new Plane();p.fly();p.stop();Bullet b = new Bullet();b.fly();b.stop();b.attack();}}interface Flyable{//全局常量public static final int MAX_SPEED = 7900;//第一宇宙速度//可以省略public static finalint MIN_SPEED = 1;//抽象方法public abstract void fly();//省略了public abstractvoid stop();}interface Attack{void attack();}class Plane implements Flyable{@Overridepublic void fly() {System.out.println("引擎起飞");}@Overridepublic void stop() {System.out.println("起落架降落");}}//多个接口class Bullet implements Flyable,Attack{@Overridepublic void fly() {System.out.println("化学起飞");}@Overridepublic void stop() {System.out.println("受阻停止");}@Overridepublic void attack() {System.out.println("具有很强的攻击性");}}//接口多继承interface AA{}interface BB{}interface CC extends AA,BB{}
3.接口是一种规范
package com.test.java;public class USBTest {public static void main(String[] args) {PC p = new PC();Flash f = new Flash();p.transferdata(f);}}class PC{public void transferdata(USB usb){usb.start();System.out.println("传输的数据");usb.stop();}}interface USB {void start();void stop();}class Flash implements USB{@Overridepublic void start() {System.out.println("U盘开始工作");}@Overridepublic void stop() {System.out.println("U盘结束工作");}}class Printer implements USB{@Overridepublic void start() {System.out.println("打印机开始工作");}@Overridepublic void stop() {System.out.println("打印机结束工作");}}
八、内部类
匿名内部类
package com.test.java;/** 1.匿名内部类不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例。* 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。** 2.格式:* new 父类构造器(实参列表)|实现接口(){* //匿名内部类的类体部分* }** 3.匿名内部类的特点* > 匿名内部类必须继承父类或实现接口* > 匿名内部类只能有一个对象* > 匿名内部类对象只能使用多态形式引用*/interface Product{public double getPrice();public String getName();}public class AnonymousTest{public void test(Product p){System.out.println("购买了一个" + p.getName() + ",花掉了" + p.getPrice());}public static void main(String[] args) {AnonymousTest ta = new AnonymousTest();//调用test方法时,需要传入一个Product参数,//此处传入其匿名实现类的实例ta.test(new Product(){public double getPrice(){return 567.8;}public String getName(){return "AGP显卡";}});}}


