堆内存:Field使用堆内存来存放
栈内存:存放引用变量
this关键字:this关键字总是指向调用该方法的对象(谁调用这个方法,this就代表谁,只是类型确定,无法确定
/*错误的代码示范*/
public class StaticAccessNonStatic
{
public void info(){
System.out.println("调用info方法");
}
public static void main(String[] args)
{
//main方法使static类型的方法
//调用main方法是该类本身,而不是该类的实例
//因此省略的this无法指向有效的对象
info(); //这里是相当与省略了this关键词
}
}
指定的对象)
1:构造器中引用该构造器正在初始化的
对象
2:在方法中引用调用该方法的对象
方法的重载注意事项:
1:方法的重载不能通过返回值来确定重载的方法
2:方法重载的参数如果为下:
public void Method1(String str){}
和
public void Method1(String... str){}
调用方法
Method1("11");//此时会调用第一个
//如果只想传入一个参数,又想调用第二个方法
Method1(new String[]{"11"});
(类)成员变量和(方法)局部变量:
成员变量:指的是类中的Field,与类共存亡
成员变量:分为类成员变量(只要类在,就可以访问类的变量)
和实例成员变量(只要实例存在没有被销毁,就可以访问实例成员变量)
局部变量:指的是方法中的变量(与成员变量不同,局部斌量除了形参之外,都必须显示初始化,否则不可以访问他们)
注意:java允许局部变量和成员变量同名,但是局部变量会覆盖成员变量,否则需要使用this
成员变量的初始化和内存中的运行机制:
class Person{
static int eyeNum;
int a;
}
public class Test{
static void main(String[] args){
Person chen=new Person();//如果我们是第一次使用Person类,系统通常会在第一次使用Person类的时候在堆内存中加载这个类,并且初始化这个类,并且为这个类的static Field成员分配内存空间,也就是eyeNum Field
当初始化完成之后,系统就会在堆内存中创建一个类的对象
}
}
如果我们是第一次使用Person类,系统通常会在第一次使用Person类的时候在堆内存中加载这个类,并且初始化这个类,并且为这个类的static Field成员分配内存空间,也就是eyeNum Field
当初始化完成之后,系统就会在堆内存中创建一个类的对象
局部变量的初始化和内存中的运行机制:
class Test{
public void swap(){
int a;//局部变量必须显式初始化之后才能使用,这就意味着在声明局部变量的时候并没有为它分配内存,存放在栈内存中,注意:(如果局部变量是基本类型变量,则直接把这个变量的值存放在对应的内存当中;如果是一个引用类型变量,则这个变量存放的是地址。栈内存无需进行系统垃圾回收,往往随着方法或者代码块的运行结束而结束)
}
}
//局部变量必须显式初始化之后才能使用,这就意味着在声明局部变量的时候并没有为它分配内存,存放在栈内存中,注意:(如果局部变量是基本类型变量,则直接把这个变量的值存放在对应的内存当中;如果是一个引用类型变量,则这个变量存放的是地址。栈内存无需进行系统垃圾回收,往往随着方法或者代码块的运行结束而结束)
封装:
/*封装一个类中的Field的变量的目的是防止对Field的值进行不正当的赋值
通常一个类就是一个小模块,在设计类的时候要求高内聚(内部数据和功能尽量在类的内部进行实现),低耦合(暴露少量的方法给外部使用)*/
public class Person
{
private String name;
private int age;
public void setName(String name){
if(name.length()>6||name.length()<2){
System.out.println("名字长度不合符");
}
else
this.name=name;
}
public String getName(){
return this.name;
}
public void setAge(int age){
if(age>100 || age<0){
System.out.println("你设置的年龄不符合要求");
}
else{
this.age=age;
}
}
public int getAge(){
return this.age;
}
public static void main(String[] args){
Person a1=new Person();
a1.setAge(44);
a1.setName("陈阔");
System.out.println(a1.getAge()+" "+a1.getName());
}
}
Pacage包:
编译:通常使用带有java -d的命令来编译
运行(加载):进入包所在的路径,使用java lee.Hello.class加载
(当运行带有包的类时,java首先会在classpath路径下寻找包的路径)
包命名规范:域名.项目名.模块名.组件名
导入包:import lee.sub.Apple;
import lee.sub...*; //导入sub目录下所有的类
import static lee.Field; //导入静态Field
java编程常用的包
java.lang(默认)
java.util(工具类,集合接口框架)
java.net(网络编程的相关类)
java.io(java输入输出的诶)
构造器:
一个构造器完全包含另一个构造器
//这里我省略了类的定义
public Apple(String name ,String color,double weight){
this(name,color);
}
继承:
当子类重写父类方法遵循的原则(形参列表相同,方法名相同,还有重写方法只能都是类方法或者实例方法)
注意:(系统查找变量的顺序)
查找方法中是否含有局部变量
查找当前类是否含有同名的Field
查找父类中是否含有同名的Field
多态:java引用变量有两个类型:如果编译时的类型和运行时的类型不一致,就可能出现多态
一个是编译时的类型:由声明该变量使用的类型决定
一个是运行时的类型:由实际赋给该变量的对象决定
class Base
{
public int books=6;
public void base(){
System.out.println("父类的普通方法");
}
public void test(){
System.out.println("父类的test方法");
}
}
public class Sub extends Base
{
public int books=7;
public void test(){
System.out.println("子类的test方法");
}
public void sub(){
System.out.println("子类的普通方法");
}
public static void main(String[] args){
Base rs=new Sub(); //此行代码,rs在编译的时候类型为Base类型
System.out.println(rs.books); //与方法不同,对象的Field并不表现出多态,这里的打印出父类的Field的值
rs.base();
rs.test(); //这里的test方法表现出子类的test方法,虽然是声明父类型的对象,却表现出子类的行为,这就是多态
//rs.sub(); //这里在编译阶段就会报错,因为在编译阶段rs是父类型,无法调用子类型的方法
}
}
注意:引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时执行它运行类型所具有的方法
但是:我们可以把父类和子类互相进行强制类型转换,这样防止在编译阶段有报错
初始化块:
静态静态初始化块:系统在类初始化阶段就执行静态初始化块,并且向父类回溯,只有它的所有父类的静态初始化块都完成之后才会完成该类的静态初始化块
普通初始化块非静态初始化块:普通初始化块和构造器的执行顺序一样,每次创建一个Leaf对象的时候,都需要先执行最顶层的初始化块和构造器,最后Leaf类的初始化块和构造器
class Root
{
static {
System.out.println("root的静态初始化块");
}
{
System.out.println("root的非静态初始化块");
}
public Root(){
System.out.println("root的无参构造函数");
}
}
class Mid extends Root
{
static {
System.out.println("mid的静态初始化块");
}
{
System.out.println("mid的非静态初始化块");
}
public Mid(){
System.out.println("mid的无参构造函数");
}
public Mid(String msg){
this();
System.out.println("Mid的带参构造器,其参数msg为"+msg);
}
public Mid(String msg,int a){
System.out.println("Mid的带两个参数的构造器");
}
}
class Leaf extends Mid
{
static {
System.out.println("leaf的静态初始化块");
}
{
System.out.println("leaf的非静态初始化块");
}
public Leaf(){
super("疯狂java讲义");
System.out.println("执行Leaf的构造器");
}
}
public class Test
{
public static void main(String[] args){
/*
预测结果:
root静态
Mid静态
Leaf静态
root非静态
root的无参构造器
Mid非静态
Mid的无参构造器
Mid的有参数的构造器
Leaf非静态
Leaf的构造器
Mid无参构造器
Mid带参数的构造器msg为疯狂java讲义
执行Leaf构造器
*/
new Leaf();
new Leaf(); //第二次执行Leaf时就不会再进行类的初始化过程
}
}