static关键字的使用
/*
* static关键字的使用
*1.static:静态的
*2.static可以用来修饰:属性、方法、代码块、内部类(不能修饰构造器)
*3.使用static来修饰属性:静态变量
* 3.1属性按是否使用static修饰分为:静态属性(静态变量)、非静态属性(实例属性)
* 实例属性;创建类的多个对象,每个对象都独立的拥有一套类中的非静态属性,
* 当修改一个对象的非静态属性时,不影响其他对象的属性
* 静态属性:创建了类的多个对象,所有对象公用一个静态变量。意味着通过某个对象修改静态变量时
* 会导致其他对象调用此静态变量时是修改过的
* 3.2 static修饰属性的其他说明:
* ①静态变量随着类的加载而加载
* ②静态变量的加载要早于对象的创建
* ③可以通过"类.静态变量"的方式调用静态变量
* ④由于类只加载一次,所以静态变量在内存中也只存在一份:存储在方法区的静态域中
* ⑤总结:
* 静态变量 实例变量
* 类 yes no (Chinese.name会报错)
* 对象 yes yes
* 3.3静态属性举例:System.out; Math.PI;
*
*4.使用static来修饰方法:静态方法
* 4.1随着类的加载而加载,可以通过"类.方法"的方式调用
* 4.2 静态方法 非静态方法
* 类 yes no (Chinese.eat()会报错)
* 对象 yes yes
*
* 4.3在静态方法中,只能调用静态的方法或属性(生命周期一致)
* 非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
* 5.static注意点:
* 5.1在静态方法内,不能使用this、super关键字
* 5.2关于静态属性和静态方法的使用均从 生命周期 的角度去理解
* 6.
* 开发中如何确定一个属性是否要声明为static?
* >>属性是可以被多个对象共享的,不会随着对象的不同而变化的
* >>类中的常量也常声明为static的
*
* 开发中如何确定一个方法是否要声明为static?
* >>操作静态属性的方通常设置为static的
* >>工具类中的方法习惯上声明为static的:Math,Arrays,Collections
* */
public class StaticTest {
public static void main(String[] args) {
// 静态属性说明情况1:
Chinese c1 = new Chinese();
c1.nameString = "zoran";
c1.age = 24;
c1.nationString = "China";// 给c1的nationString属性赋值 China;没有给c2的nationString属性赋值
Chinese c2 = new Chinese();
c2.nameString = "ply";
c2.age = 20;
System.out.println(c2.nationString);// 打印c2的nationString,输出China
// 静态属性说明情况2:
Chinese c3 = new Chinese();
c3.nameString = "zoran";
c3.age = 24;
c3.nationString = "China";// 先给c3的nationString赋值China
Chinese c4 = new Chinese();
c4.nameString = "ply";
c4.age = 20;
c4.nationString = "CHN";// 再给c2的nationString赋值CHN
System.out.println(c3.nationString);// 打印c1的nationString:CHN
System.out.println(Chinese.nationString);// 类.静态变量的方式调用 输出为:CHN
System.out.println("***************************************");
//静态方法
Chinese.eat();//通过"类.方法"的方式调用静态方法,输出:Chinese can eat
}
}
class Chinese {// 创建类
String nameString;
int age;
static String nationString;
public static void eat() {
// info(); 报错 不能在静态方法中调用非静态方法
// walk(); 不报错,可以在静态方法中调用静态方法
// nameString="tom";报错,不能在静态方法中调用非静态属性
// nationString="china";不报错,可以在静态方法中调用静态属性,其实是Chinese.naionStirng 省略了类名
System.out.println("Chinese can eat");
}
public void info() {
System.out.println("name : " + nameString + "age : " + age);
}
public static void walk() {
}
}
//static关键字的应用举例
public class CircleTest {
public static void main(String[] args) {
Circle c1 = new Circle();
Circle c2 = new Circle();
Circle c3 = new Circle(3.5);
System.out.println("c1的id: "+ c1.getId());//c1的id: 1001
System.out.println("c2的id: "+ c2.getId());//c2的id: 1002
System.out.println("c3的id: "+ c3.getId());//c3的id: 1003
System.out.println("共创建了"+ Circle.getTotal()+ "个圆");//通过"类.属性"的方式调用静态属性
}
}
class Circle{
private double radius;
private int id;
private static int total=0;//记录创建的圆的个数
private static int init = 1001 ;//多个对象共享id,每个圆对象都有自己的id
public Circle() {
total++;
id = init++;//每创建一个圆对象,id自动+1
}
public Circle(double redius) {
this();//调用构造器,相当于 total++;id=init++;
this.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;
}
private double findArea() {
return 3.14*radius*radius;
}
}
//举例2
/*
* 编写一个类实现银行账户的概念,包含的属性有:账号、密码、存款余额、利率、最小余额
* 定义封装这些属性的方法。账号要自动生成
* 编写主类,使用银行账户类输入输出3个储户的上述信息
* 考虑:那些属性可以设计成static属性
*
* */
public class Accout {
//属性
private static int inid=1000;
private int id;//用于自动生成id
private String password = "123456";
private double balance;
private static double rate;
private static double MIN_BALANCE = 1.0;
//构造器
public Accout() {
id=inid++;
}
public Accout(String password, double balance) {
this();
this.password = password;
this.balance = balance;
}
//gs方法
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public static double getRate() {
return rate;
}
public static void setRate(double rate) {
Accout.rate = rate;
}
public static double getMIN_BALANCE() {
return MIN_BALANCE;
}
public static void setMIN_BALANCE(double mIN_BALANCE) {
MIN_BALANCE = mIN_BALANCE;
}
public int getId() {
return id;
}
public double getBalance() {
return balance;
}
@Override
public String toString() {
return "Accout [id=" + id + ", password=" + password + ", balance=" + balance + "]";
}
}
public class AccoutTest {
public static void main(String[] args) {
Accout a1= new Accout();
Accout a2= new Accout("123123",520.1314);
Accout.setRate(0.0012);
Accout.setMIN_BALANCE(100);
System.out.println(a1);//默认调用对象的toString方法
System.out.println(a2);
System.out.println(a1.getRate());//0.012
System.out.println(a2.getMIN_BALANCE());//100.0
}
}
单例模式
/*
* 单例设计模式
* 1.就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例
* 2.如何实现
* 饿汉式
* 懒汉式
* 3.区分饿汉式和懒汉式
* 饿汉式:
* 对象加载时间过长 但是 线程安全
*
* 懒汉式:
* 延迟对象的创建 但是 线程不安全 --->多线程再改
*
* */
//单例模式饿汉式
public class SingletonTest {
public static void main(String[] args) {
Bank b1 =Bank.getInstanceBank();
Bank b2 =Bank.getInstanceBank();
System.out.println(b1==b2);//true
}
}
class Bank{
//1.私有化类的构造器
private Bank() {
}
//2.内部创建类的静态对象
private static Bank instanceBank = new Bank();
//3.提供公共的静态的方法返回类的对象
public static Bank getInstanceBank() {
return instanceBank;
}
}
//单例模式的懒汉式
public class SingletonTest2 {
public static void main(String[] args) {
Order o1 = Order.getInstance();
Order o2 = Order.getInstance();
System.out.println(o1==o2);//true
}
}
class Order{
//1.私有化类的构造器
private Order(){
}
//2.声明当前类的静态对象,不初始化
private static Order instance =null;
//3.声明公共的静态方法返回当前类的对象
public static Order getInstance() {
if( instance == null) {
instance = new Order();
}
return instance;
}
}
理解main方法的语法(了解即可)
/*
* main()的使用说明
* 1.main()方法作为程序的入口
* 2.是一个普通的static方法
* 3.main()可以作为与控制台交互的方式(之前使用Scanner)
* */
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<args.length;i++) {
args[i]="args_ "+i;
System.out.println(args[i]);
}
}
}
类的成员之四:代码块
/*
* 类的成员之四:代码块(初始化块)
*
* 1.代码块的作用:
* 用来初始化类 或者 对象
* 2.代码块如果有修饰,只能用static
* 3.分类: 静态代码块 和 非静态代码块
*
* 4.静态代码块
* >内部可以有输出语句
* >静态代码块随着类的加载而执行且只执行一次(只会在类加载的时候执行一次)
* >如果一个类中声明了多个静态代码块,按照声明的先后顺序执行
* 且静态代码块的执行优先于非静态代码块的执行(因为静态代码块随着类加载执行)
* >静态代码块内部只能调用静态的属性与方法
* 作用:初始化类的信息
*
* 5.非静态代码块
* >内部可以有输出语句
* >非静态代码块随着类的对象的创建而执行
* >每创建一个对象,就会执行一次
* >如果一个类中声明了多个非静态代码块,按照声明的先后顺序执行
* >非静态代码块可以调用静态的属性方法或非静态的属性方法
* 作用:
* 可以在创建对象时,将对象的属性进行初始化
*
* 对属性可以赋值的位置:
* ①默认初始化
* ②显式初始化
* ③构造器初始化
* ④"对象.属性"、对象.set()方法"
* ⑤在代码块中赋值
*
* 执行顺序:由父及子,静态先行
* */
public class BlockTest {
public static void main(String[] args) {
String descString = Person.descString;//hello static block
Person p1 = new Person();//hello block
Person p2 = new Person();//hello block
Person.info();//代码块不输出
System.out.println(p1.age);//10
System.out.println(Person.descString);// i am a good person
}
}
class Person {
//属性
String nameString;
int age;
static String descString="i am a person";
//构造器
public Person(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public Person() {
}
//代码块
//1.静态代码块
static{
System.out.println("hello static block");
descString = " i am a good person";
}
static{
System.out.println("hello static block-1");
}
//2.非静态代码块
{
System.out.println("hello block");
age =10;
}
//方法
public void eat() {
System.out.println("people can eat");
}
@Override
public String toString() {
return "Person [nameString=" + nameString + ", age=" + age + "]";
}
public static void info() {
System.out.println("i am a happy people");
}
}
final关键字的使用
/*
* final:最终的
* 1.final可以用来修饰的结构:类、方法、变量
* 2.final 修饰类:此类不能被其他类继承
* 比如:String System StringBuffer 等类
* 3.final 修饰方法:表名此方法不能被重写
*
* 4.final 修饰变量:此时的"变量"称为常量
* 4.1 final修饰属性:可以赋值的位置有:显式初始化、代码块中初始化、构造器中初始化
* 4.2 final修饰局部变量
* 尤其式final修饰形参时,表名此形参是一个常量,调用此方法给常量形参赋值后
* 就只能在方法体内使用此形参,不能重新赋值
* static final 用来修饰一个属性:全局常量(尤其是接口)
* */ 看这些结论理解一下就行
public class FinalTest {
final int width = 10;
public void doWidth(){
// width =20; 不能再次被赋值
}
public static void main(String[] args) {
int num = 10;
num = num+5;
}
}
final class FinalA{
}
// class B extends FinalA{} 类FinalA不能被继承
class AA{
public final void show() {}
}
class BB extends AA{
// public void show() {} 不能重写
}
抽象类与抽象方法
/*
* abstract关键字的使用
* 1.abstract:抽象的
* 2.abstract可以用来修饰的结构:类、方法
*
* 3.abstract修饰类:抽象类
* >此类不能实例化
* >抽象类中一定有构造器,便于子类对象实例化时调用(子类对象实例化的全过程)
* >在开发中,都会提供抽象类的子类,让子类对象实例化完成相关操作
*
* 4.abstract修饰方法:抽象方法
* >抽象方法只有方法的声明,没有方法体 public abstract void method();
* >包含抽象方法的类一定是一个抽象类,反之,抽象类中不一定有抽象方法(但是没必要)
* >子类重写了父类中的所有抽象方法,才可以实例化
* >若子类没有重写父类中的所有抽象方法,则子类也是一个抽象类
*
* */
public class AbstractTest {
public static void main(String[] args) {
//一旦Person类抽象了,就不能实例化
// Person p1 = new Person();
// p1.eat();
}
}
abstract class Person{
String nameString;
int age ;
public Person() {
super();
}
public Person(String nameString, int age) {
this.nameString = nameString;
this.age = age;
}
//抽象方法
public abstract void eat();
public void walk() {
System.out.println("people can walk");
}
}
abstract class Student extends Person{
public Student(String nameString ,int age) {
super(nameString ,age);
}
// public void eat() {
// System.out.println("sutdent must eat more");
// }
}
/*
* abstract使用的注意点:
* 1.abstract不能修饰:属性、构造器等
* 2.abstract不能修饰私有方法(因为声明为private的方法不能重写)、静态方法(声明为static的方法不可成重写)、final的方法(不能重写)
*
* */
//练习题
/*
* 编写一个Employee类,声明为抽象类
* 包含以下三个属性:name id salary
* 提供必要的构造器和抽象方法:work()
*
* */
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();
}
public class Manager extends Employee{
private double bonus;
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
public Manager(double bonus) {
super();
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("管理员工的人");
}
}
public class CommonEmployee extends Employee {
@Override
public void work() {
System.out.println("普通员工在一线工作");
}
}
public class EmployeeTest {
public static void main(String[] args) {
//多态的使用
Employee manager = new Manager("zoran",1001,9000,5666);
manager.work();
//不使用多态
CommonEmployee commonEmployee = new CommonEmployee();
commonEmployee.work();
}
}
//应用
//抽象类的应用:模板方法的设计模式
public class TemplateTest {
public static void main(String[] args) {
Template template = new SubTemplate();
template.spendTime();
}
}
abstract class Template{
//计算某段代码执行所需要的时间
public void spendTime() {
long start = System.currentTimeMillis();
this.code();//不确定的部分、易变的部分
long end = System.currentTimeMillis();
System.out.println("执行代码花费的时间为:" + (end - start));
}
public abstract void code();
}
class SubTemplate extends Template{
@Override
public 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.使用interface来定义一个接口
* 2.Java中,接口和类是两个并列的结构
* 3.如何定义接口:定义接口中的成员
*
* 3.1 JDK7以及以前:
* 只能定义全局常量和抽象方法
* >全局常量:public static final的 (可以省略)
* >抽象方法:public abstract 的 可以省略)
* 3.2 JDK8:除此以外还可以定义静态方法、默认方法
*4.接口中不能定义构造器,即:接口不能实例化
*5.在java开发中,接口通过让 类去实现(implements)接口的方式来使用
* 如果实现类覆盖了接口中的所有抽象方法,则此实现类可以实例化
* 如果实现类没有覆盖接口中的所有方法,则此实现类仍为一个抽象类
*6.Java类可以实现多个接口:打破了单继承的局限性
* 格式: class AA extends BB implements CC,DD{}
*7.接口和接口之间可以继承,而且可以多继承
*8.接口的使用可以体现多态性
*9.接口可以看成一种规范
*
* 面试题:抽象类与接口有哪些异同?
*
@author shkstart
@create 2021-04-27-14:41
*/
public class InterfaceTest {
public static void main(String[] args) {
System.out.println(Flyable.MAX_SPEED);
System.out.println(Flyable.MIN_SPEED);
Plane p =new Plane();
p.fly();
p.stop();
p.attack();
}
}
interface Attackable{
void attack();
}
interface Flyable{
//全局常量
public static final int MAX_SPEED = 7900;
public static final int MIN_SPEED = 1;
//其中 pubilc static final 可是省略
//int MAX_SPEED=7900;
//int MIN_SPEED=1;
//抽象方法
public abstract void fly();
public abstract void stop();
//其中 public abstract 可是省略
//void fly();
//void stop();
}
class Plane implements Flyable,Attackable {
@Override
public void fly() {
System.out.println("plane can fly");
}
@Override
public void stop() {
System.out.println("plane can stop");
}
@Override
public void attack() {
System.out.println("warplane can attack");
}
}
class Bullet extends Object implements Flyable,Attackable,CC{
@Override
public void attack() {
}
@Override
public void fly() {
}
@Override
public void stop() {
}
@Override
public void method1() {
}
@Override
public void method2() {
}
}
//********************************************
interface AA{
void method1();
}
interface BB{
void method2();
}
interface CC extends AA,BB{
}
/**
* 接口的使用
*1.接口使用上满足多态性
*2.接口实际上定义了一种规范
* @author shkstart
* @create 2021-04-27-15:04
*/
public class USBTest {
public static void main(String[] args) {
Computer computer = new Computer();
Flash flash = new Flash();
computer.transferDtata(flash);
}
}
class Computer{
public void transferDtata(USB usb){//USB usb = new Flash();
System.out.println("具体的传输数据的细节");
usb.start();
usb.stop();
}
}
interface USB{
void start();
void stop();
}
class Flash implements USB{
@Override
public void start() {
System.out.println("start working");
}
@Override
public void stop() {
System.out.println("stop working");
}
}
//应用
/*接口的应用:代理模式
*
* */
public class NetWorkTest {
private static ProxyServer proxyServer;
public static void main(String[] args) {
Server server = new Server();
ProxyServer proxyServer = new ProxyServer(server );
proxyServer.browse();
}
}
interface NetWork{
public void browse();
}
//被代理类
class Server implements NetWork{
@Override
public void browse() {
System.out.println("真实的服务器访问网络");
}
}
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work) {
this.work = work;
}
public void check() {
System.out.println("联网之前的检工作");
}
@Override
public void browse() {
check();
work.browse();
}
}
类的成员之五:内部类
```java
/*
* 类的内部成员之五:内部类
* 1.Java中允许将一个类A声明在另一个类B中,A为内部类,B为外部类
*
* 2.内部类的分类:成员内部类(静态与非静态)、局部内部类(方法内、代码块内、构造器内)
*
* 3.成员内部类:
*
* 一反面,作为外部类的成员:
* >可以调用外部类的结构
* >可以被static修饰
* >可以被四种不同的权限修饰
*
* 另一方面,作为一个类:
* >类内可以定义 属性 方法 构造器等
* >可以用final修饰,表示此类不能被继承
* >可以用abstract修饰,表示此类不能被实例化
*
*4.关注如下三个问题即可
* 4.1如何实例化成员内部类的对象
* 4.2如何在成员内部类中区分调用外部类的结构
* 4.3开发中 局部内部类的使用
*
* */
public class InnerClassTest {
public static void main(String[] args) {
//创建Dog的实例(静态的成员内部类)
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态的成员内部类)
Person p1 = new Person();
Person.Bird bird = p1.new Bird();
bird.sing();
bird.display("黄鹂");
}
}
class Person{
String nameString;
int age;
public void eat() {
System.out.println("people can eat");
}
//静态成员内部类
static class Dog{
String nameString;
int age;
public void show() {
System.out.println("i am a dog");
}
}
//非静态成员内部类
class Bird{
String nameString ;
public void sing() {
System.out.println(" i am a bird");
Person.this.eat();//调用外部类的方法
}
public void display(String nameString) {
System.out.println(nameString);//方法的形参
System.out.println(this.nameString);//内部类的属性
System.out.println(Person.this.nameString);//外部类的属性
}
}
public void method() {
//局部内部类
class AA{
}
{
//局部内部类
class BB{
}
}
}
public Person() {
//局部内部类
class CC{
}
}
}
```java
/* 4.3开发中 局部内部类的使用
*
*
*/
public class InnerClassTest1 {
//开发中很少见
public void method() {
//局部内部类
class AA{
}
}
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable() {
//创建一个实现了Comparable接口的类:局部内部类
class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 0;
}
}
return new MyComparable();
//方式二
// return new Comparable() {
//
// @Override
// public int compareTo(Object o) {
// // TODO Auto-generated method stub
// return 0;
// }
//
// };
//
}
}