包装类、object、单例模式、final、抽象类
/*包装类*/ /* byte Byte short Short int Integer long Long char Character float Float double Double boolean Boolean
基本数据和其包装类:作为成员变量时的默认初始值的差异: int -- Integer 0 null */ class WrapDemo { public static void main(String[] args) {
//包装类对象 /* 把基本数据类型包装类除了 Character类之外,其他的7个都有两个构造方法
基本数据类型xx; xx对应包装类的构造方法: public xx的包装类(xx x){} public xx的包装类(String x){}
这里传递的x值表示该包装类型对象的值; Integer i = new Integer(17);//i = 17 i = new Integer("123");// i = 123 使用第二种构造方法可能会引发 类型转换异常; Integer:凡是涉及到整数的操作,Integer类里都有相应的方法来处理;
Character类没有public Character(String c){}
*/ Boolean b = new Boolean("tRuE");//除了true之外(不区分大小写),其他的默认都是false
/* static Boolean FALSE 对应基值 false 的 Boolean 对象。 static Boolean TRUE 对应基值 true 的 Boolean 对象。
*/ b = Boolean.FALSE;//FALSE == new Boolean(false); System.out.println("b= " + b);
//十进制和 二进制,八进制,十六进制的转换
/* Integer: 有3个静态的方法可以完成: static String toBinaryString(int i) 以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式。 static String toHexString(int i) 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式。 static String toOctalString(int i) 以八进制(基数 8)无符号整数形式返回一个整数参数的字符串表示形式。 */ System.out.println(Integer.toBinaryString(-100)); //byte byteValue() 以 byte 类型返回该 Integer 的值。 Integer i = new Integer(17); byte by = i.byteValue(); System.out.println(by); /* int compareTo(Integer anotherInteger)在数字上比较两个 Integer 对象。 */
System.out.println(i.compareTo(new Integer(12)));//1 /* int intValue() 以 int 类型返回该 Integer 的值。
包装类 -->基本类型: 调用xxxValue(); int ret = age.intValue();
基本类型 -->其包装类
new 包装类(基本类型的值); new Integer(17); */
int age = i.intValue();
/* static int parseInt(String s) 将字符串参数作为有符号的十进制整数进行解析。
String --> 基本类型 */ age = Integer.parseInt("17"); /* static Integer valueOf(int i) 基本类型 -->包装类类型 和 new Integer(int i); 返回一个表示指定的 int 值的 Integer 实例。 static Integer valueOf(String s) String --> Integer: new Integer(String s); 返回保存指定的 String 的值的 Integer 对象。
*/ //static boolean isDigit(char ch) 确定指定字符是否为数字。 //判断的是0 ~9之间的数字 System.out.println(Character.isDigit('A'));//false char c = '8';// System.out.println(Character.isDigit(c));
String s = "1214542S"; System.out.println("----------------"); int i1 = 12; int i2 = 12;
System.out.println(i1 == i2);//相等
Integer in1 = new Integer(12); Integer in2 = new Integer(12);
System.out.println(in1 == in2);//不相等的,两个对象
in1 = 12; in2 = 12; System.out.println("--->"+(in1 == in2));//true /* 这里涉及到了一个享元模式: 只缓存[-128,127]区间的数字,Byte,Short,Integer,Long 都是一样的 */ in1 = 128; in2 = 128; System.out.println("--->"+(in1 == in2));//true
/* 装箱和拆箱:
int Integer 装箱: 把基本数据类型 --> 它所对应的包装类类型 Integer i = new Integer(int value);
拆箱: 包装类类型 --> 它所对应的把基本数据类型 int i2 = i.intValue();
Java5开始提供了自动装箱和拆箱的功能; 自动装箱: 可以把一个基本数据类型的值直接赋给 其包装类对象 Integer age = 17;
Object就可以接受一切类型了; Object o = false; o = 123; 自动拆箱: 可以把一个包装类对象直接赋给一个基本数据类型的变量 int age2 = age;
*/
Integer age2 = 17;
int age3 = age2;
} }
class ObjectDemo { /* 类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。 */ public static void main(String[] args) {
String[][] arr = {{"A"}};
Object o = arr; System.out.println(arr.getClass()); /* 常见方法:
boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。 equlas默认的比较的是 堆里地址,和 == 一样,都是比较地址
有的时候我们不需要比较地址,比如有的时候我们不关心地址,只关心值,咋办? 此时就要求子类去覆写该方法
比如Integer类: public boolean equals(Object obj) { if (obj instanceof Integer) { return this.value == ((Integer)obj).intValue(); } return false; }
int hashCode() 返回该对象的哈希码值。
String toString() 返回该对象的字符串表示。
*/
//equals
System.out.println(new Integer(1).equals(new Integer(1)));//true System.out.println(new Object().equals(new Object()));//false
System.out.println(new String() == new String());//false System.out.println(new String().equals(new String()));//true
System.out.println(new Object().hashCode());//每个对象的hashCode都会不一样 System.out.println(new Object().hashCode());
Object o1 = new Object();
System.out.println(o1.hashCode()); System.out.println(o1.hashCode()); /* String toString() 返回该对象的字符串表示 以字符串的形式描述了对象状态;//描述对象
hexHashCode 我们打印对象,其实打印的是对象的toString()方法 对象类型的全限定名 + @ + 对象十六进制的hashCode
一般情况下建议每个类都覆写toString()
对象 --> String
本质上打印对象,其实就是在打印对象的toString()方法 */ ObjectDemo od = new ObjectDemo(); System.out.println(od);//ObjectDemo@c05d3b System.out.println(od.toString());//ObjectDemo@c05d3b int hashCode = od.hashCode();// //static String toHexString(int i) 转16进制 String hexHashCode = Integer.toHexString(hashCode);
System.out.println(hexHashCode);
System.out.println(new Person("Will","男",17).toString()); System.out.println(new Person("Lucy","女",15));
Object p = new java.util.Date();
System.out.println("p.getClass()-->"+p.getClass().getName()); } }
class Person {
private String name; private String gender;
private Integer age; public Person(String name,String gender,Integer age) { this.name = name; this.gender = gender; this.age = age; } @Override//表示覆写 public String toString() { return "[ name= " + this.name +",性别= " + this.gender +", 年龄= " + this.age +"]"; } }
/*
普通代码块
*/
class CodeDemo1
{
public static void main(String[] args)
{
{
//普通代码块
int a = 10;
System.out.println("--->" + a);
}
//System.out.println(a);//访问不到
}
}
/* 构造代码块: 定义在 类里面,方法外面:
直接写在类中的代码块: 优先于构造方法执行,每次实例化对象之前都会执行构造代码块。 */ class CodeDemo2 {
public CodeDemo2(){ System.out.println("构造方法"); }
{ System.out.println("构造代码块"); }
public static void main(String[] args) { System.out.println("Main"); new CodeDemo2(); new CodeDemo2(); new CodeDemo2(); System.out.println("Hello World!"); } }
/* 静态代码块: 就是在构造代码块之前,加上一个 static关键字:
使用static 修饰的构造代码块: 优先于主方法执行,优先于构造代码块执行,不管有创建多少对象,静态代码块只执行一次,可用于给静态变量赋值; */
class CodeDemo3 {
static String name ;
public CodeDemo3() { System.out.println("构造方法!"); }
{ System.out.println("构造代码块!"); }
static { name = "AA"; System.out.println("静态代码块!"); } public static void main(String[] args) { System.out.println("Main!"); new CodeDemo3(); new CodeDemo3(); System.out.println("end"); } }
import java.lang.reflect.*;
class Cat { /* 使用private修饰构造方法之后,在该类之外的地方就不能再创建对象了. 结论不一定,因为要把反射除开;
//项目开发经常有这样的一个需求:
某一个对象,只需要存在一个就OK了; 有且只有一个对象;
古代皇帝,
*/ private Cat(){ //super(); System.out.println("cat"); } }
class PrivateDemo {
public static void main(String[] args) throws Exception { Class<Cat> clz = Cat.class; //得到class对象的三种方式之一
Constructor<Cat> c = clz.getDeclaredConstructor();//得到私有私有的构造函数 c.setAccessible(true);//暴力反射 -- 私有的东东就可以在外部进行访问了 Cat cat = c.newInstance();//实际上是调用类里面的无参构造方法创建对象
System.out.println(cat); } }
/* 单例模式: 保证整个项目运作期间某一个对象有且只有一个;
单例模式: 1.饿汉式 2.懒汉式 */
class Singleton { //饿汉式----每次调用的时候不用做创建,直接返回已经创建好的实例。这样虽然节省了时间,但是却占用了空间,实例本身为static的,会一直在内存中带着 private static final Singleton instance;// = new Singleton();
static { instance = new Singleton(); } public static Singleton getInstance() { return instance; } //把构造方法私有化,不允许外界再创建对象 private Singleton(){} }
class Singleton2 { //懒汉式 懒汉式则是判断,在用的时候才加载,会影响程序的速度 ,线程不安全的在并发的情况下。如果两个线程,我们称它们为线程1和线程2,在同一时间调用getInstance()方法,如果线程1先进入if块,然后线程2进行控制,那么就会有两个实例被创建。 private static Singleton2 instance = null; public static Singleton2 getInstance() { if(instance == null) { instance = new Singleton2(); }
return instance; } private Singleton2(){} }
class SingletoDemo { public static void main(String[] args) { // Singleton s1 = Singleton.instance; // Singleton s2 = Singleton.instance;
Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
Singleton2 s3 = Singleton2.getInstance(); Singleton2 s4 = Singleton2.getInstance();
System.out.println(s3 == s4); } }
final class FinalCLass { }
//class Sub extends FinalCLass {} //FinalDemo.java:5: 错误: 无法从最终FinalCLass进行继承
class Super { //修饰符没有先后关系 final public void show() { } }
class Sub extends Super { //FinalDemo.java:20: 错误: Sub中的show()无法覆盖Super中的show() /**public void show() { } */ }
class FinalDemo { //全局常量 public static final int MAX_VALUE = Integer.MAX_VALUE; public static void main(String[] args) { /* final修饰的变量表示常量: 对常量有一个规范小规定:常量名得全部大写 若该常量名由多个单词组成, 单词字符全部写,而且单词于单词之间使用下划线分割;
public static final int MAX_VALUE
final修饰的变量不能赋值? 最多只能赋值一次,一旦有值之后就不能被修改了;
面试题: 当final修饰一个引用类型变量的时候, 那到底是引用不能变(引用地址不能变),还是引用对象的值不能变呢?
答: 是引用的地址不能变,对象里的内容是可以变的; */
final double PI = 3.14; //pi = 0.618;//FinalDemo.java:38: 错误: 无法为最终变量pi分配值
System.out.println(PI); //说明地址不能变 final String s = new String(); //s = new String();//FinalDemo.java:59: 错误: 无法为最终变量s分配值
//地址不变,但是对象内容的
final StringBuilder sb = new StringBuilder("AAA");//字符串 System.out.println(sb);
sb.append("BBB");//追加 System.out.println(sb);
} }
abstract class OOXX { } /*
抽象方法: 使用abstract修饰的方法,但是没有方法体(没有{}),只有方法声明,抽象方法强制子类覆写
一旦一个类有了抽象方法,那么该类也必须声明为抽象类; 但是抽象类可以没有抽象方法;
抽象类不能实例化,不能创建对象
抽象类必须得有子类,自己的功能才能得以运行;
抽象类的方法只是定义了子类应该具备的行为, 但是没有给出怎么去完成行为的功能代码; 交给子类去根据自身特殊情况去完成该父类声明的功能;
抽象方法也成为 钩子方法; 回调方法
抽象类里可以有普通方法,
抽象类是类的一种特殊情况:据有类的一切特点,但是 不能实例化; 一般的都得带有抽象方法 */
abstract class Tuxing { //建议写在方法的最前面,为了醒目 abstract public double getZC();
public Tuxing(){ // System.out.println("---"); } }
class Sanjiaoxing extends Tuxing { private double a; private double b; private double c; public Sanjiaoxing(double a,double b,double c) { this.a = a; this.b = b; this.c = c; }
//必须覆写 public double getZC(){
//new Tuxing();//ERROR return a + b + c; }
}
//矩形 class Juxing extends Tuxing {
public Juxing() {
super(); } //忘了覆写 public double getZC(){ //new Tuxing();//ERROR return 0; }
} class AbstractDemo2 { public static void main(String[] args) { double ret = new Sanjiaoxing(3,4,5).getZC();//AbstractDemo2.java:35: 错误: Sanjiaoxing是抽象的; 无法实例化 System.out.println(ret); } }