this和super关键字
this用于指代当前对象;super用于指代父类对象
- this()表示调用另外一个构造器,super()表示调用父类中的某个构造器,()中的参数决定调用的是哪个构造器
public class A {
public A() {
//需要调用A(String)这个构造器方法
this("zhangsan"); //调用当前类中的另外一个构造器
}
public A(String name) {
System.out.println("name:"+name);
}
}
//另外的写法
public A(String name) {
this(); //在当前构造器中调用另外一个构造器方法的语句必须是构造器方法中的第一句
System.out.println("name:"+name);
}
//语法错误
public A(String name) {
if(name!=null)
this();
System.out.println("name:"+name);
}
- this.成员属性用于表示当前对象的某个成员,一般用于局部变量和属性名称一致的场景下。super.成员属性用于表示父类中定义的某个属性,一般用于子类中覆盖定义了某个父类属性的场景下
- this.成员方法()用于表示当前对象的某个成员方法;super.成员方法()用于表示当前类的父类中定义的某个成员方法,一般用于覆盖定义时【就近原则】
- 在static方法中不允许使用this/super之类关键字
关键字final(意思是最终的、不可变的)
修饰属性
- final修饰变量时,变量被必须初始化,并且不能被修改。初始化可以定义nal变量时直接初始化或者在构造函数中初始化
修饰局部变量
public class A {
public void pp() {
// final int kk=123; 声明的同时直接进行赋值操作
final int kk; //先声明后赋值
System.out.println("其它操作");
kk=222;
// kk++;final变量一旦赋值则不允许进行修改操作
System.out.println(kk);
}
}
修饰方法
-final修饰方法则该方法不能被子类重写
修饰类
- final修饰一个类,则该类不能被继承
- 通过private构造器也达到了类似的不允许继承的效果,但是要求类中的所有构造器都是私有
扩展
- 表示字串的3种类型String、StringBuer、StringBuilder都是nal类型的类,所以都不允许继承
总结
- final 属性上可以声明的同时直接赋值或者在构造器中赋值
- final临时变量,可以声明的同时赋值或者在第一次使用之前进行赋值
– 注意:nal类型的变量一旦赋值则不允许修改,但是如果是复杂类型是不允许修改地址,但是可以修改属性 - final方法表示这个方法不允许在子类中重新定义(覆盖\重写)
- final类表示这个类不允许被继承
设计模式
设计模式就是由专家总结出来的在某种情况下针对某种问题的最佳解决方案,是知识,是思想
-
没有编码,需要按照指导思想针对具体问题自行编码实现
-
专家总结出来的
-
没有银弹
-
参考网站:https://www.runoob.com/design-pattern/design-pattern-tutorial.html
-
总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural
Patterns)、行为型模式(Behavioral Patterns)
单例模式
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
单例模式有多种写法,最常见的是懒汉模式和饿汉模式
饿汉单例模式
优点:没有加锁,执行效率会提高
缺点:类加载时就初始化,浪费内存
编程实现:
- 私有构造器
- 静态的私有属性
- 公共的静态方法
懒汉单例模式
懒汉式:主要是针对饿汉式中不管是否需要使用对象都先创建对象所引起的内存浪费
优点:由于采用栏延迟处理的方式,所以比较节约内存
缺点:在多线程不能正常工作
静态static关键字
用于修饰成员,包括成员属性【类属性或者静态属性】、成员方法【类方法或者静态方法】
- 随着类加载,随着类消失
- 优先于对象,用类名直接访问
public class A {
public static int kk=123;//静态属性
public static void pp() {}//静态方法
public static void main(String[] args) {
//针对静态属性,即可以直接以类名的方式进行调用,也可以创建对象后当作普通属性进行调用
System.out.println(A.kk);//采用类名称直接调用
A.pp(); //采用类名称直接调用
A a=new A();
System.out.println(a.kk); //采用对象名的方式进行调用
a.pp();//采用对象名的方式进行调用
}
}
静态属性
static属性是当前类的所有对象所共有的共同属性(只有一个,而普通属性各个对象都有自己的,相互隔离),任何一个当前类对象修改这个属性,所有其他类对象的这个属性都会受影响
执行过程:
- 静态属性,在类加载完毕后则自动进行静态资源处理
A a;这里并没有创建A对象,但是C自动创建了,执行了static C c=new C(); - 如果是调用new操作
非静态属性
构造器
执行顺序: 静态属性—属性—构造器
访问的方式
可以使用“类名.静态属性名”或者“对象名.静态属性名”的方式进行访问。
定义常量
命名规则:名称全大写,下划线分词
- 声明语法:public static nal double MIN_NUMBER = 0.1;
- 声明的同时直接进行初始化
----public static nal double MIN_NUMBER = 0.1; - 先声明后在static静态块中赋值
public static final double MIN_NUMBER;
static{
MIN_NUMBER = 0.1;
}
静态方法
- 因为可以直接使用”类名.方法名”的形式直接调用静态方法,静态方法执行时很有可能并没有构建对象,所以在静态方法中不允许使用this/super之类用于指定对象的关键字
public class B{
private Random random;
public static void pp() {
System.out.println("pp....");
//静态方法的调用没有要求必须构建B对象,所以很有可能random根本不存在,要求在静态方法
中不能访问非静态成员
// System.out.println(random);
// 在static方法中不允许出现this或者super关键字
}
public static void main(String[] args) {
B.pp();//调用当前类中的static方法,可以直接写方法名称pp()
}
}
- 当然在静态方法中允许创建对象,并调用对象方法
- 静态方法只能直接访问静态成员,不能直接访问非静态成员
静态块
public class A{
static { //类内,所有方法之外
System.out.println("静态代码块");
}
}
- 类在执行时需要通过一个叫作类加载器的组件将程序加载到内存中,类在运行时一般不会发生变化,所以类不会频繁加载,在整个运行过程中只加载一次,而且常驻内存
- 静态块在类加载完毕后自动执行,而且只执行一次
public class B{
static {
System.out.println("static...");
}
public static void main(String[] args) {
}
}
非静态块
非静态块在类内且在所有的方法之外,非静态块并不会在类加载后自动执行,而是在构建当前对象时自动执行。new一次则会执行一次,执行时机在构造器之前执行
static相关问题
-
父类中定义的静态方法(类方法)是否可以通过”子类名.静态方法名”的方式进行调用?
----可以,因为继承的特性 -
父类中定义的静态方法(类方法)是否可以在子类中进行覆盖定义(重写)?
-------可以,但是方法签名必须一致,方法必须为static定义
特殊点:静态方法也允许通过对象进行调用
静态块没有覆盖定义的概念,如果父子类中都定义了静态块,一定是先执行父类中的静态块,然后运行子类中的静态块
- 加载顺序为先父后子—先执行父类中定义的静态属性和静态块
- 然后执行初始化操作—先处理父类中的成员属性和非静态块,再执行父类构造器;后执行子类的定义内容
静态导入
在一个类中反复使用到某个类中的静态方法,如果使用静态导入则在当前类中不需要再写类名称
double a1=-12.345;
System.out.println(Math.abs(a1));
System.out.println(Math.cos(a1));
System.out.println(Math.sin(a1));
在JDK5当中提供了导入静态方法的import语句。
- 语法:import static java.lang.Math.*; - 导入Math类中的所有静态方法
- 注意要求使用JDK1.5+版本,否则编译不通过
import static java.lang.Math.*;
public class Test1 {
public static void main(String[] args) {
double a1 = -12.345;
System.out.println(abs(a1));
System.out.println(cos(a1));
System.out.println(sin(a1));
}
}