构造器不能被继承,故不能被重写override,但可以被重载overload。
为什么不可以被重写?
构造器不是方法,那么用来修饰方法特性的所有修饰符都不能用来修饰构造器(并不等与构造器具备这些特性,虽然不能用static修饰构造器,但它却有静态特性)构造器只能用
public private protected这三个权限修饰符,且不能有返回语句。
每个类必须有构造函数,子类不会覆盖父类的构造函数,而且必须的是在一开始就要调用父类的构造函数,通过super方法来调用。
所以可以根据不同的参数存在多个构造函数的情况。
重载
发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
返回类型不是方法签名的一部分,不能有俩个名字相同,参数类型也相同却返回不同类型值的方法。
不可变性:
String类中使用final关键字修饰字符数组来保存字符串的,private final char value[],所以String对象不可变。
但是呢,在StringBuilder,StringBuffer都继承自AbstractStringBuilder类,在其中也是字符数组保存字符串char[] value,但是它没有用final关键字修饰,所以这俩种对象都是可变的。
StringBuilder、StringBuffer的构造方法都是调用父类构造方法也就是AbstractStringBuilder实现的,大家可以自行查阅源码。
AbstractStringBuilder.java
abstract class AbstractStringBuilder implements Appendable,CharSequence{
/**
* The value is used for character storage.
*/
char[] value;
/**
* The count is the number of characters used.
*/
int count;
AbstractStringBuilder(int capacity){
value=new char[capacity];
}
}
线程安全性
String
中的对象是不可变的,也就可以理解为常亮,线程安全。
AbstractStringBuilder
是StringBuilder
与StringBuffer
的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf
等公共方法。
StringBuffer
对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
StringBuilder
并没有对方法进行同步锁,所以是非线程安全的。
性能
每次对 String
类型进行改变的时候,都会生成一个新的 String
对象,然后将指针指向新的 String
对象。
StringBuffer
每次都会对 StringBuffer
对象本身进行操作,而不是生成新的对象并改变对象引用。
相同情况下使用 StringBuilder
相比使用 StringBuffer
仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
String、StringBuffer、StringBuilder:
String
(对象不可变,每次都是新建对象)StringBuilder
(没有同步锁方法,非线程安全)StringBuffer
(对其对象进行操作,且对方法都加了同步锁,线程安全)自动装箱与拆箱
Integer i=100;
//等价于,自动装箱
Integer i=new Integer (100);
//Integer i= Integer.valueOf(100);valueOf()返回的都是个Integer对象。
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
int ii = i
//等价于
int ii = i.intValue()//直接返回value值即可
==================================================
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i1==i2); //true
System.out.println(i3==i4); //false
/*i1和i2会进行自动装箱,执行了valueOf函数,它们的值在(-128,128]这个范围内,它们会拿到SMALL_VALUES数组里面的同一个对象SMALL_VALUES[228],它们引用到了同一个Integer对象,所以它们肯定是相等的。*/
/*i3和i4也会进行自动装箱,执行了valueOf函数,它们的值大于128,所以会执行new Integer(200),也就是说它们会分别创建两个不同的对象,所以它们肯定不等。*/
=======================================================
Double i1 = 100.0;
Double i2 = 100.0;
Double i3 = 200.0;
Double i4 = 200.0;
System.out.println(i1==i2); //false
System.out.println(i3==i4); //false
/*
因为对于Integer,在(-128,128]之间只有固定的256个值,
所以为了避免多次创建对象,我们事先就创建好一个大小为256的Integer数组SMALL_VALUES,
所以如果值在这个范围内,就可以直接返回我们事先创建好的对象就可以了。
但是对于Double类型来说,因为在这个范围内个数是无限的。
在某个范围内的整型数值的个数是有限的,而浮点数却不是。
Double里面的做法很直接,就是直接创建一个对象,所以每次创建的对象都不一样。
public static Double valueOf(double d) {
return new Double(d);
}
*/
抽象类中可以不包含抽象方法,但是包含抽象方法的类必须声明为抽象类。
从语法形式上看:
》成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;
》成员变量可以被 public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
从变量在内存中的存储方式来看:
》如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例对象的,而对象存在于堆内存,
》局部变量则存在于栈内存。
从变量在内存中的生存时间上看:
成员变量是对象的一部分,它随着对象的创建而存在;
而局部变量随着方法的调用而自动消失。
赋值情况:
》成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外:被 final修饰的成员变量也必须显式地赋值),
》而局部变量则不会自动赋值。必须定义后使用。
new 运算符,new 创建对象实体(对象实体在堆内存中;对象引用存储在栈内存中)。
对象引用指向对象实例(对象引用存放在“栈内存”中)。
》一个对象引用可以指向 0 个或 1个对象(一根绳子可以不系气球,也可以系一个气球);
》一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。Vehicle veh1 = new Vehicle();再有veh2=veh1,俩个引用指向同一个对象。但是veh1引用已经成为垃圾回收机制的处理对象了。
引用就像是文件夹的快捷方式,可以通过这个快捷方式,找到文件夹,修改文件夹的内容,但是删除这个快捷方式却不会对文件夹有影响。
java的基本类型变量存储在“栈”中,引用类型的对象存储在“栈”中,对象的引用地址存储在“堆”中。堆(存储快,放基本类型变量和对象的引用);栈(存储慢,放对象和数据)。
参考:https://www.cnblogs.com/lj820403/p/7482946.html
特点:
》构造方法名一定与类同名。
》构造方法无返回值类型(void也不行)
》构造方法可以没有(默认一个无参构造方法),也可以有多个构造方法。他们之间构成重载关系。
》如果定义有参构造函数,则无参构造函数将被自动屏蔽。
》构造方法不能手动调用,在创建类实例的时候自动调用构造方法。
作用:
初始化对象,为对象赋初值。
简化我们为类字段赋值的代码。
与普通方法的区别:
》构造方法一定与类同名,普通方法就可以不用。
》构造方法无返回值类型(void也不行),普通方法可以返回。
静态方法和实例方法调用的区别:
静态方法,通过类名调用即可。
实例方法,通过实例调用即可。
static的作用主要在于创建独立于具体对象的域变量或者方法。
静态变量和静态方法,都是属于类本身,而不是属于那个类的对象。
1==静态方法和实例方法调用的区别:
静态方法,通过类名调用即可。
实例方法,通过实例调用即可。
WHY?存在调用方式的差异性?????
类的静态方法,静态变量是在类装载的时候装载的,这时候还没有产生对象。所以【类名。方法名】调用静态方法。
2==静态方法于实例方法在加载期的区别:
java虚拟机(jvm)只有一个堆区被所有线程所共享,堆区中有一块特殊的区域叫做方法区(静态区),该区域也是被所有线程共享的。
jvm保存的所有的信息都在这个方法区中,所以方法区在加载方法信息的时候是统一对待的,无论静态方法或实例方法,都在类第一次被使用时加载,时机上没有任何区别的
3==静态方法和实例方法的内存区别:
静态方法在程序开始时生成内存,实例方法在程序运行中生成内存;所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法。
静态速度很快,但是多了会占内存,所以不管是任何语言都是对内存和磁盘的操作。why?静态方法速度快?
静态内存是连续的,因为是在程序开始时就生成了;而实例申请的是离散的空间,所以当然没有静态方法速度快,而且静态内存是有限制的,太多了程序会启动不了。
main函数的执行过程:
4==完全可以把实例方法写成静态方法!!!从以下两个方面来看:
》 面向对象的角度上来说:
在选择使用实例化方法或静态方法时,如果方法和实例化对象具有逻辑上的相关性,就应该使用实例化对象 反之使用静态方法。
=================================
》 线程安全、性能、兼容性上来看: 选用实例化方法为宜。
========================================
》从语言本身来看:
JAVA是面向对象的语言,既然面向对象,那最好还是用实例化对象方法最合适。
参考博客:https://blog.csdn.net/adam_swx/article/details/102861275