一篇文章搞定Java设计结构以及对象与类

Java基本程序设计结构

 java程序都是从main方法开始

.java->.class     .class程序才能使用java命令来运行

 int a =3 ;     //用来存储整型---》计算机中使用的存储的都是二进制

编码 类似     010101张    0000000三    固定的二进制值代表着固定的编码

基本类型 

int   4个字节     32位      范围正负20亿

short   2个字节   16位   

long    8个字节    64位  

byte   1个字节   8位   范围  -127---128

float    4个字节    32位

double   8个字节    64位

boolean

char  2个字节  ,有特定的char类型需要更多字节来表示

包装类

1.为什么要有包装类?

Java是一个面向对象的编程语言,而基本类是不是一个对象,涉及到集合的时候,基本类型用不了

2.自动拆装箱

定义:能够使基本类型与其对应的包装器类型之间自动相互转换

自动拆装箱是属于编译器行为,当编译器对 .java 源代码进行编译时,如果发现你没有进行拆箱,那么编译器来来帮你拆;如果你没有装箱,那么编译器来帮你装

public class Test {
 
    // 自动拆箱
	@Test
	public void break() {
		Integer i = new Integer(100);
		int a = i;
	}
	
	// 自动装箱
	@Test
	public void install() {
		Integer i = 100;
	}
}

注:

装箱

  Integer x =Integer.valueOf(9);

拆箱

Integer A=new Integer(8);
int a=A.intValue();

3.128陷阱问题

128陷阱出现的原因就是Integer的valueOf方法中有一个存储[-128-127]的catch数组,这个数组就相当于一个缓存,当我们定义的数在-128-127之间时,就直接返回该内存中的地址

Integer中的valueOf方法

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

所以当我们用==比较两个用Integer定义值为128的数时,会返回false,此时a和b是封装在两个对象中,比较应用.equals()方法

几个测试样例

public class test {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 1;
        System.out.println(a==b);
    }
}

一篇文章搞定Java设计结构以及对象与类_第1张图片


public class test {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        System.out.println(a==b);
    }
}

 一篇文章搞定Java设计结构以及对象与类_第2张图片


public class test {
    public static void main(String[] args) {
        Integer a = 128;
        Integer b = 128;
        System.out.println(a==b);
        System.out.println(a.equals(b));
    }
}

 一篇文章搞定Java设计结构以及对象与类_第3张图片

类型转换 

1.自动类型转换

一篇文章搞定Java设计结构以及对象与类_第4张图片

  示例代码

    int i = 128;
    double b = i;//128.0

2.强制类型转换

强制转换格式:(类型)变量名

注意点:

父类子类对象的强制类型转换的示例

必须是父类对象指向子类引用,强制转换成子类之后之后才能使用子类中的方法

People类

public class People {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Student类

一篇文章搞定Java设计结构以及对象与类_第5张图片

String 

1.为什么字符串不可变?

  • final修饰类
  • final修饰的char数组
  • 整个类内不存在任何一个对数组内容做修改的方法,即使是String的某些截取字符串的api,也是生成新的字符串对象

Java设计者认为共享带来的高效率远远胜过于提取,拼接字串带来的效率

2.Stringbuilder和StringBuffer

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象

StringBuilder-线程不安全 StringBuffer-线程安全

StringBuilder 相较于 StringBuffer 有速度优势

在多线程的情况下使用StringBuffer

final关键字

修饰类:不可以再被继承了

修饰方法:不可以被重写

修饰变量:不可以对其尽享复制,但可以通过某些骚操作对其内部的值进行更改

并发:防止指令重排序


下面是final修饰变量时,修改内部值的骚操作的例子

public class test {
    public static void main(String[] args) {
        final int [] arr = new int[]{1};
        //不能这样对final修饰的变量进行修改
        arr = new int[]{123};
        //可以通过这样对final修饰的变量内部进行修改(骚操作)
        arr[0]=2;
    }
}

static final 类常量

归类所有

枚举类型

变量的取值只在一个有限的集合内

针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。
例如:
Size s = Size.MEDIUM;
Size 类型的变量只能存储这个类型声明中给定的某个枚举值 或者 null null 表示这
个变量没有设置任何值

 面向对象编程

什么是面向对象编程?和面向过程有什么区别,优缺点是什么?

优点:以人类解决问题的方法,思路,习惯和步骤来设计相应的应用程序

把构成问题的各个事物分解成各个对象,提高程序的重用性,灵活性和可拓展性

三大特征

  • 封装:将数据和方法结合在一起,对数据的访问者隐藏了数据的实现方式
  • 继承:复用已经存在的方法和域,子类继承父类的属性和方法
  • 多态:一个行为具有多个不同表现形式或形态的能力

多态实现的必要条件

1. 子类必须继承父类

2. 必须有重写

3. 父类引用指向子类对象

一个实例:

父类

public class Animal {
	public  void  eat() {
		System.out.println("所有的动物都很能吃。。。。。");
	}
	public  void  run() {
		System.out.println("所有的动物都很能吃。。。。。");
	}
}

子类

public class Cat extends Animal{
	public  void  eat() {
		System.out.println("所有的猫都能吃。。。。。");
	}
	public void jump() {
		// TODO Auto-generated method stub
		System.out.println("所有的猫都能跳。。。。");
	}
}

测试类

public class Test {
    public static void main(String[] args) {
        Animal animal = new Cat() ;
        animal.eat();
    }
}

运行结果:

一篇文章搞定Java设计结构以及对象与类_第6张图片

 题外话

 一篇文章搞定Java设计结构以及对象与类_第7张图片

强制类型转换后:

public class Test {
    public static void main(String[] args) {
        Animal animal = new Cat() ;
        animal.eat();

        //但是如果调用Cat类里有但Animal类中没有的方法就会报错
        //animal.jump();

        
        //需要强制转换成Cat类
        Cat cat = (Cat) animal;
        cat.jump();
    }
}

 一篇文章搞定Java设计结构以及对象与类_第8张图片

 

构造函数 

特征

  1. 要和类名一样
  2. 可以重载
  3. 如果没有定义构造函数的话,会自动生成一个无参的构造函数
  4. 没有返回值,连void都没有
  5. 单例模式下,构造函数要私有化

访问修饰符 

同一个类 同一个包 不同包中的子类 不同包中的非子类
private
default
protect
public
 

类加载的执行顺序

从main方法所在类加载

从上往下执行静态初始化语句初始化块,每涉及到加载类的时候,最后执行构造函数

静态方法,每次调用才会执行

看一个案例:

public class InitializeDemo {
    private static int k = 1;
    private static InitializeDemo t1 = new InitializeDemo("t1");
    private static InitializeDemo t2 = new InitializeDemo("t2");
    private static int i = print("i");
    private static int n = 99;
    static {
        print("静态块");
    }
    private int j = print("j");
    {
        print("构造块");
    }
    public InitializeDemo(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }
    public static int print(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }
    public static void main(String args[]) {
        new InitializeDemo("init");
    }
}
  • 首先初始化静态变量,k、i、n全部为0,然后顺序执行语句 k=1,执行了
  • 然后初始化t1,此时n、i均为0,所以初始化t1的成员变量j;输出 1:j i=0 n=0 2:构造块 i=1 n=1
  • 再初始化t1的构造方法:3:t1 i=2 n=2
  • 然后初始化t2
  • 先初始化t2的成员j变量输出 4:j i=2 n=2 5:构造块 i=3 n=3
  • 再初始化t2的构造方法:6:i i=5 n=5
  • 执行i=print(i);输出:7:i i=6 n=6
  • 再执行n=99
  • 执行静态块:输出 8:静态块 i=7 n=99
  • 最后初始化init的成员变量:9:j i =8 n=100 10:构造块 i=9 n=101
  • 初始化init的构造方法:11:init i=10 n=102

一篇文章搞定Java设计结构以及对象与类_第9张图片

总结

  1. 静态只在类加载的时候执行,且执行一次。  
  2. 非静态只在实例化的时候执行,且每次实例化都执行。  
  3. 静态在非静态之前执行。  
  4. 静态属性和静态块的执行顺序取决于编码顺序,对它们一视同仁。  
  5. 非静态属性和构造块的执行顺取决于编码顺序,对它们也一视同仁。  
  6. 最后执行构造方法。  

(静态属性=静态代码块)> (非静态属性 = 构造块)> 构造方法

你可能感兴趣的:(Java,java,开发语言)