1.在创建对象时,为对象分配存储空间,编译器调用相应的构造器。
2.构造器的名字必须与类名完全相同。
3.在java中 初始化与创建捆绑在一起,两者不能分离。
4.构造器没有返回值,与返回值为空不同
不写构造方法会有有默认的一个无参的构造方法
public class AAA {
public AAA() {}
}
为了让方法名相同而形式参数不同的构造器同时存在,必须用到方法重载。
重载的方法参数类型列表独一无二
@Slf4j
public class AAA {
public AAA() {
log.info("hello AAA()");
}
public AAA(String name) {
log.info("hello AAA(i)"+name);
}
}
基本类型 不能是包装类型Integer,Double会提示错误
1.byte 1字节(8位)
2.boolean 1字节(8位)
3.short 2字节(16位)
4.char 2字节(16位)
5.int 4字节(32位)
6.float 4字节(32位)
7.long 8字节(64位)
8.double 8字节(64位)
较小类型会被自动转换为较大的类型,反之需要强制类型转换
void printInt(int value){
System.out.println("print(int value),"+value);
}
void printDouble(double value){
System.out.println("print(double value),"+value);
}
@Test
void test(){
short valueShort = 5;
int valueInt = 5;
double valueDouble = 5.0;
printInt(valueShort);
printInt((int)valueDouble);
printDouble(valueShort);
printDouble(valueInt);
}
顺序
byte—short—int—long—float—double
char—int—long—float—double
int—long—float—double
short—int—long—float—double
long—float—double
float—double
例子5.2.2-1在最后
这是不行的,因为很有可能直接用 f(x)这种方式调用方法,编译器无法区分出调用的函数。
就是无参的构造方法,没有,编译器会自动创建
如果你自家创建了一个有参数的构造函数,编译器不会再创建。
public class Person {
public void eat(Apple apple){
Apple peeled = apple.getPeeled();
System.out.println("Yummy "+peeled.getPeel());
}
}
@Data
public class Apple {
private String peel ;
public Apple(){
this.peel= "hasPeel";
}
Apple getPeeled(){
System.out.println("Apple getPeeled now peel:"+this.getPeel());
return Peeler.peel(this);
}
}
public class Peeler {
static Apple peel(Apple apple){
apple.setPeel("noPeel");
System.out.println("Peeler peel apple peel:"+apple.getPeel());
return apple;
}
}
@Test
void test(){
new Person().eat(new Apple());
}
public class Flower {
private int petalCount = 0;
private String s = new String("null");
Flower(int petals) {
petalCount = petals;
System.out.println( "Constructor w/ int arg only, petalCount= "+ petalCount);
}
Flower(String ss) {
System.out.println("Constructor w/ String arg only, s=" + ss);
s = ss;
}
Flower(String s, int petals) {
this(petals);
//! this(s); // Can't call two!
this.s = s; // Another use of "this"
System.out.println("String & int args");
}
Flower() {
this("hi", 47);
System.out.println("default constructor (no args)");
}
void print() {
//! this(11); // Not inside non-constructor!
System.out.println("petalCount = " + petalCount + " s = "+ s);
}
public static void main(String[] args) {
Flower x = new Flower();
x.print();
}
} ///:~
this(petals)
构造方法必须在起始处
this.s = s
; 参数s和数据成员s同名,用this.s来代表当前数据成员
略
垃圾回收器只知道释放由new分配的内存
可以定义finalize()
方法
当垃圾回收器准备好释放对象占用的存储空间,首先调用finalize()
方法,在下次垃圾回收动作发生时,才会真正回收对象占用的内存。
1.对象可能不被垃圾回收
2.垃圾回收并不等于“析构”
3.垃圾回收只与内存有关
通过某种创建对象方式以外的方式为对象分配了存储空间,但Java中一切皆为对象。
这种特殊情况主要发生在使用“本地方法”,即调用非Java代码
不要过多的使用finalize()
无论是垃圾回收还是终结都不保证一定发生
以本人浅薄的汉语造诣是完全看不懂他到底在翻来覆去的说些什么,反正就是不用finalize()
@Data
public class Book
{
private String name ;
private boolean checkedOut = false;
public Book( String name,boolean checkedOut){
this.name = name;
this.checkedOut = checkedOut;
}
public void checkIn(){
checkedOut = false;
}
protected void finalize(){
System.out.println(""+this.name+":finalize()");
if(checkedOut){
System.out.println("忘记checkIn "+this.name);
}
}
}
@Test
void testFinalize(){
Book novelOne = new Book("novelOne",true);
novelOne.checkIn();
new Book("novelTwo",true);
Book novelThree = new Book("novelThree",true);
System.gc();
}
novelTwo没有定义引用,调用了finalize方法,这样
1.引用记数 略
2.停止-复制
先暂停程序的运行,将所有或者的对象从当前堆复制到另一个堆
3.标记-清扫
遍历所有引用,标记存活对象。全部标记后,清理没有标记的对象。
参考:
Java编程思想读书笔记(一)第1~13、16章
例子5.2.2-1
public class PrimitiveOverloading {
static void prt(String s) {
System.out.println(s);
}
void f1(char x) { prt("f1(char)"); }
void f1(byte x) { prt("f1(byte)"); }
void f1(short x) { prt("f1(short)"); }
void f1(int x) { prt("f1(int)"); }
void f1(long x) { prt("f1(long)"); }
void f1(float x) { prt("f1(float)"); }
void f1(double x) { prt("f1(double)"); }
void f2(byte x) { prt("f2(byte)"); }
void f2(short x) { prt("f2(short)"); }
void f2(int x) { prt("f2(int)"); }
void f2(long x) { prt("f2(long)"); }
void f2(float x) { prt("f2(float)"); }
void f2(double x) { prt("f2(double)"); }
void f3(short x) { prt("f3(short)"); }
void f3(int x) { prt("f3(int)"); }
void f3(long x) { prt("f3(long)"); }
void f3(float x) { prt("f3(float)"); }
void f3(double x) { prt("f3(double)"); }
void f4(int x) { prt("f4(int)"); }
void f4(long x) { prt("f4(long)"); }
void f4(float x) { prt("f4(float)"); }
void f4(double x) { prt("f4(double)"); }
void f5(long x) { prt("f5(long)"); }
void f5(float x) { prt("f5(float)"); }
void f5(double x) { prt("f5(double)"); }
void f6(float x) { prt("f6(float)"); }
void f6(double x) { prt("f6(double)"); }
void f7(double x) { prt("f7(double)"); }
void testConstVal() {
prt("Testing with 5");
f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5);
}
void testChar() {
char x = 'x';
prt("char argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testByte() {
byte x = 0;
prt("byte argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testShort() {
short x = 0;
prt("short argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testInt() {
int x = 0;
prt("int argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testLong() {
long x = 0;
prt("long argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testFloat() {
float x = 0;
prt("float argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
void testDouble() {
double x = 0;
prt("double argument:");
f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
}
public static void main(String[] args) {
PrimitiveOverloading p =
new PrimitiveOverloading();
p.testConstVal();
p.testChar();
p.testByte();
p.testShort();
p.testInt();
p.testLong();
p.testFloat();
p.testDouble();
}
}