面向对象
深拷贝,浅拷贝
- Person p2 = new Person(p1)是调用了构造器,对属性进行复制,并且new了一个新地址,p1 p2指向不同,互不影响,是深拷贝
- 而Person p2 = p1则是直接让p2指向p1,p1的改变影响p2,是浅拷贝
为何要封装
- 有时候需要对属性进行crud操作,倘若有Animal类,有属性legsNumber,腿子的数量就不能是单数,通过自定义set方法可以解决逻辑问题
- 账户类中有余额属性,在set时也需要进行判断,可以自定义set,而把属性本身设为private,防止直接访问修改(当然你要说用反射那当我没说)
匿名对象
- 用完一次之后就等垃圾回收
- 如果Person p1 = new Person(“zhangsan”,15, new Pet(“年年”))这样new出来的Pet对象是不会被回收的
什么是javaben
- public类
- private属性
- 有get set方法
- 有public无参构造器
this关键字和super关键字
- this就是本类,super就是上一级父类
- this.可以调属性:this.name = name;
- this.可以调方法:在参数多的构造器中this.参数少的构造器
- 当子类定义有参的构造方法时,super(形参列表)必须与父类构造一致
- this()和super()都是构造方法,并且都要求放在第一行,但是this()和super()只会同时出现其中一个,一般用this(形参)针对父类构造,super(形参)针对子类构造
示例:
class Person{
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
class Student extends Person{
private int id;
public Student(String name, int age, int id) {
//形参要求齐全
super(name, age);//先super()构造
this.id = id;
}
}
继承的权限
- 权限大小:public>protected>缺省>private
- 每“出一层”,可见范围少一个
同包建立任意类(子类,普通类):private不可见了
跨包建立子类:缺省也不可见了
跨包建立普通类(非子类):protected也不可见了
实际开发中一般只用public和private
重载和重写(覆写)
- 重载:形参类型or数量不同,构造器就是重载
- 重写:保证子父类结构一致,给与子类方法独特的个性
- 属性也是可以重写的,参数名相同,可以更改类型
重写后如何调用父类方法?
class Super{
public void tell(){
System.out.println("我是你爹");
}
}
class Sub extends Super{
public void tell(){//覆写
System.out.println("***********");
super.tell();//调用父类的被覆写的方法
super.tell();//可以调用多次,并且位置不限
System.out.println("我是你儿子");
}
}
public class Test {
public static void main(String[] args) {
Sub A = new Sub();
A.tell();
}
}
编译看左,运行看右(虚拟方法调用)
-
编译看左,运行看右:(虚拟方法调用)
-
Person A = new Man(); 左边决定能用什么属性or方法,右边决定用谁的属性or方法
-
在编译期只能调用父类中声明的方法,但在执行期实际执行的是子类重写的方法
-
多态性是一个运行期行为,编译器看不出来
instanceof方法
如果 对象属于xx类,那么对象 instansof XX就返回ture
System.out.println(new AllComments() instanceof Object);//true
System.out.println(new Father() instanceof Son);//false
包装类
例如:Object.Number.Integer
Boolean
-
可传String和boolean
-
忽略大小写
System.out.println(new Boolean("sadasd"));//fanlse System.out.println(new Boolean(""));//fanlse System.out.println(new Boolean("TrUe"));//true System.out.println(new Boolean(true));//true
Float
- 可传double float String
示例:
Float A = new Float(12.3);
//double自动转成float
Float A2 = new Float(12.3f);
Float B = new Float("12.3");
//String自动转成float
Float C = new Float("12.3aaa");
//编译正常,运行报错,Float没有定义怎么处理字母
默认值问题
包装类的默认值是null 如Integer:null,普通类的默认值如int:0
自动装箱
可以直接把基本数据类型赋值给包装类
Integer A = 1;
相当于
Integer A = new Integer(1);
自动拆箱
Integer A = 1;
int a = A;
相当于
Integer A = new Integer(1);
int a = A.intValue();
String到包装类or普通数据类型(parse)
-
为什么不能直接Integer A = (Integer)(new String(“1111”)呢
-
因为Integer和String两个类没有子父类关系
-
应该使用parseXxx方法来解析
Integer A = Integer.parseInt((new String("111")));//111 Double B = Double.parseDouble(A.toString());//111.0 Float C = Float.parseFloat("111");//111.0 Boolean D = Boolean.parseBoolean("true");//D就是true
toString
- Object中的默认toString是输出地址值
- 自定义类需要重写toString
static
- 不用new就可以用,随类的加载而加载
- static属性:既可以类调用,也可以对象调用
- static方法:只能调用static属性和方法,不能访问普通方法;不能使用this和super
final和abstract
final
-
定义不能继承的类
-
定义不能重写的方法
-
定义常量属性
-
final和abstract不相同
-
可以先声明后定义
public final class NoInherit{ } //不能继承的类 public static final void tell(){} //不能重写的方法 public static final int a; //静态常量,final一般都是跟static连用 final a; a = 1; //此后a就不能变了 //a=1之前不能调用,会报错
abstract
- abstract不能修饰private方法、static方法、final方法
- 抽象类的抽象方法更多是一种规范
- new 抽象类 or 接口 的时候要用代码块包裹所有需要重写的abstract类,如:
代码块
- 执行顺序:静态代码块—>普通代码块—>构造器
- 且静态代码块只随类加载一次
- 有继承关系时,先调用父类的静态代码块
示例:
public class PersonTest{
public static void main(String[] args) {
new Person();
new Person();
}
}
class Person{
public Person(){
System.out.println("构造器");
}
{
System.out.println("代码块");
}
static{
System.out.println("静态代码块");
}
}
内部类和JVM类的加载规则
在定义类的时候可以把另一个类作为class类型的属性
JVM的类加载规则 :
- static类型的属性和方法,在类加载的时候就会存在于内存中。
- 要想使用某个类的static属性和方法,那么这个类必须要加载到JAVA虚拟机中。
- 非静态内部类不能有静态成员变量或静态方法
静态属性or方法不用new就加载,而非静态的内部类需要new才能实例化,显然是矛盾的,所以非静态内部类不能有静态成员变量或静态方法(不考虑反射)