疯狂Java笔记
StringBuilder > StringBuffer > String
String:每次对String类型进行修改时都会生成一个新的对象,所以经常改变内容的字符串最好不要去用String. StringBuffer有insert和append方法,而StringBuilder比StringBuffer效率更高
多态:父类对象指向子类对象,并调用子类重写的方法
访问权限:
protect: 当前类,子类,同一包中,不同包不可见
default: 当前类,同一包中
第四章:
4.6深入数组
1、栈内存和堆内存
每个方法都会建立自己的内存栈,在这个方法内定义的变量会逐个放入栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁。因此,所有在方法中定义的局部变量都是放在栈内存中的,在程序中创建一个对象,这个对象将被保存到运行时数据区中,以便反复利用,这个运行时数据区就是堆内存。
定义并初始化一个数组后,在内存中分配了两个空间,一个用于寻访数组的引用变量,另一个用于存放数组本身。
第五章 面向对象(上)
1、static 修饰的方法属于类,
静态区域块 只执行一次,不会因为多次创建对象而执行。
普通成员方法可以访问静态成员,但是静态方法不能访问非静态成员。
2、
第六章 面向对象(下)
System.out.println(Boolean.compare(true, false)); true > false , 1 System.out.println(Boolean.compare(true, true)); true == true, 0 System.out.println(Boolean.compare(false, true)); false < true, -1
使用abstract修饰类时,表明这个类只能被继承;当使用abstract修饰方法时,表明这个方法必须由子类提供实现(即重写)
( abstract 不能修饰成员变量,不能修饰局部变量,不能修饰构造器,不能修饰static方法)
而final修饰的类不能被继承,final修饰的方法不能被重写。
toString
返回该对象的字符串表示.
Object
类的 toString
方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@
”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:getClass().getName() + '@' + Integer.toHexString(hashCode())
==和equals
常量池:专门用于管理在编译时被确定并保存在已编译的.class文件中的数据。
当Java程序直接使用形如“hello”的字符串直接量(包括可以在编译时就可以计算出来的字符串值)时,JVM将会使用常量池来管理这些字符串;当使用new String(“hello")时,JVM会先使用常量池来管理"hello"直接量,再调用String类的构造器创建一个新的String对象,新创建的String对象被保存在堆内存中。换句话说,new String ("hello") 一共产生了两个字符串对象。
String s1 = "疯狂JAVA"; String s2 = "疯狂”; String s3 = "JAVA"; String s4 = "疯狂“ + ” JAVA"; // s1 == s4 true String s5 = s2 + s3; //s5后面的字符串值不能在编译时确定下来, s1 ==s5 false String s6 = new String("疯狂JAVA"); //s6引用堆内存中新创建的String对象。 s1 == s6 false
equals() 时Object类提供的一个实例方法,可以判断两个对象的值相等,重写equals()就是提供自定义的相等标准。
equals对于字符串时比较内容的,
对于非字符串变量来说,"=="和"equals"方法的作用是相同的都是用来比较其对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。
比如: class A { A obj1 = new A(); A obj2 = new A(); } 那么:obj1==obj2是false obj1.equals(obj2)是false 但是如加上这样一句:obj1=obj2; 那么obj1==obj2 是true obj1.equals(obj2) 是true
类成员:
类成员不能访问实例成员,类成员属于类,类成员的作用域比实例成员的作用域更大。
抽象类:
父类的方法不确定时,用abstract修饰,
类也要用abstract修饰 , 即抽象类。
当子类继承的父类是抽象类时,需要把抽象类中的所有抽象方法实现。
抽象类不能实例化。 抽象类可以不包含抽象方法。一旦类中有abstract方法,一定要声明成抽象类。
final修饰符
表示该变量一旦获得了初始值就不可以被改变,一旦获得初始值,就不能被重新赋值
不能对final形参赋值。
final修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。
final修饰符的一个重要用途就是定义“宏变量”
final String str1 = "疯狂"; final String str2 = "Java" String s3 = str1 + str2; System.out.println(s1 == s3); true
final不可被重写,可重载。
final类不能有子类
不可变类
接口
一个类实现一个接口,就要求该类将所有的接口都实现
接口不能被实例化。
支持多继承;
实现接口方法时,必须使用public访问控制修饰符。接口里面的方法都是public的,而子类 重写父类方法时访问权限只能更大或者相等。所以实现类接口方法只能使用public访问权限。
接口是多程序之间通信的标准。
接口和抽象类的区别:
1接口里只能包含抽象方法、静态方法和默认方法,不能为普通方法提供方法实现;抽象类完全可以包含普通方法
2接口中只能定义静态常量,不能定义普通成员变量;抽象类里则既可以定义普通成员变量,也可以定义静态变量
3接口不包含构造器,抽象类包含构造器,抽象类的构造器不是用来创建对象,而是让其子类调用这些构造器来初始化抽象类
4接口不能包含初始化块,抽象类则可以包含
5 一个类最多只能有一个直接父类,包含抽象类。但一个类可以直接实现多个接口,通过实现多个接口弥补单继承
面向接口编程:
1简单工厂模式:
2命令模式:
枚举类
enum关键字和class、interface关键字的作用大致相似
public enum SeasonEnum { SPRING, SUMMER, FALL, WINTER; }
枚举类一旦显式定义了带参数的构造器,列举枚举值时就必须对应的传入参数
public enum Gender { //这个枚举必须调用对应的构造器来创建 MALE("男"), FEMALE("女"); private final String name; //枚举类的构造器只能使用private修饰 private Gender(String name) { this.name = name; } }
-----------------
内部类:
非静态内部类的构造器必须使用外部类对象来调用。
class Out { class In { public In(String msg) { System.out.println(msg); } } } class SubClass extends Out.In { public SubClass(Out out) { out.super("hello"); } } public class CreateInnerInstance { public static void main(String[] args) { //Out.In in = new Out().new In("测试信息"); Out.In in; Out out = new Out(); in = out.new In("测试信息"); } }
匿名内部类
abstract class Device { private String name; public abstract double getPrice(); public String getName() { return name; } public Device() {} public Device(String name) { this.name = name; } } public class AnonymousInner { public void test (Device d) { System.out.println("购买了一个" + d.getName() + ", 花掉了" + d.getPrice()); } public static void main(String[] args) { AnonymousInner ai = new AnonymousInner(); ai.test(new Device("电子示波器") { public double getPrice() { return 67.5; } }); Device d = new Device() { { System.out.println("匿名内部类的初始化块..."); } public double getPrice() { return 56.2; } public String getName() { return "键盘"; } }; ai.test(d);a } }
interface A { void test(); } public class ATest { public static void main(String[] args) { int age = 8; //age = 2; 加这个将出现错误,因为age已经是final类型 A a = new A() { public void test() { System.out.println(age); // 匿名局部类访问的内部变量,可以用final修饰,也可以不用final修饰,但必须按照final修饰的方式来用 } }; a.test(); } }
Lambda 不懂,未看
对象与垃圾回收
对象的软、弱和虚引用,不太明白
JAR文件,没看
3
第七章
1、Java程序的入口--main方法
public static void main(String[] args) public :Java类由JVM调用,为了让JVM可以自由的调用这个main方法,所以用public把这个方法暴漏出来 static:JVM调用这个主方法时,不会先创建该主类的对象,然后通过对象来调用该主方法。JVM直接通过该类来调用主方法 void: 主方法由JVM调用,该主方法的返回值讲返回给JVM,这没有任何意义 (String[] args)谁调用方法,谁负责为形参赋值,main方法由JVM调用,即args形参应该由JVM负责赋值。所以JVM将args数组设置成一个长度为0的数组 public class ArgsTest { public static void main(String[] args) { System.out.println(args.length); // 输出0 for (String arg : args) System.out.println(arg); } } //某参数包含空格,用“”括起来 java ArgsTest "Java Spring"
2、Scanner获取键盘输入
Scanner包含两个方法 hasNextXxx():是否还有下一个输入项,hasNextInt, hasNextLong等,如果只是判断是否包含下一个字符串,则直接使用hasNext();NextXxx()
获取下一个输入项,
//从文件读取 import java.util.Scanner; import java.io.File; public class ScannerFileTest { public static void main(String[] args) throws Exception { Scanner sc = new Scanner(new File("ScannerFileTest.java")); System.out.println("ScannerFileTest.java文件内容如下:"); while (sc.hasNextLine()) { System.out.println(sc.nextLine()); } } }
3、hashCode
hash算法原理:Set接受一个元素时根据对象的地址算出hasCode,看它属于哪一个区间,在区间调用equals方法。
1、如果两个对象相同,他们的hashCode一定相同,故重写equals必须重写hashCode
2、如果两个对象的hashCode相同,他们并不一定相同
String中的hashCode已被重写,哈希计算公式可以计为s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]; import java.lang.System; public class IdentityHashCodeTest { public static void main(String[] args) { String s1 = new String("Hello"); String s2 = new String("Hello"); // s1 和 s2的hashCode返回值相同 System.out.println(s1.hashCode() + "-------" + s2.hashCode()); // identityHashCode根据对象地址计算,可以唯一的标识该对象。 System.out.println(System.identityHashCode(s1) + "--------" + System.identityHashCode(s2)); String s3 = "Java"; String s4 = "Java"; //s3和s4是相同的字符串对象, System.out.println(System.identityHashCode(s3) + "-------" + System.identityHashCode(s4)); } }
4、Runtime类
import java.lang.Runtime; public class RuntimeTest { public static void main(String[] args) throws Exception { Runtime rt = Runtime.getRuntime(); /* System.out.println("处理器数量:" + rt.availableProcessors()); System.out.println("空闲内存量:" + rt.freeMemory()); System.out.println("总内存数:" + rt.totalMemory()); System.out.println("可用最大内存数:" + rt.maxMemory()); */ rt.exec("notepad.exe"); } }
7.3常用类
Object类:
clone方法需要实现Cloneable
class Address { String detail; public Address(String detail) { this.detail = detail; } } class User implements Cloneable { int age; Address address; public User(int age) { this.age = age; address = new Address("广州天河"); } public User clone() throws CloneNotSupportedException { return (User)super.clone(); } } public class CloneTest { public static void main(String[] args) throws CloneNotSupportedException { //克隆只是对对象里各实例变量进行“简单赋值”,如果实例是引用类型,像address是引用,这样原来的引用和克隆的引用指向内存中同一个实例。图P247 User u1 = new User(29); User u2 = u1.clone(); System.out.println(u1 == u2); // false,不同对象 System.out.println(u1.address == u2.address); // 统一饮用 } }
Objects类:
String类:
int compareTo(String anotherString):比较两个字符串的大小,如果两个字符串的字符串序列相等,返回0;不相等,从两个字符串第0各字符开始比较,返回第一个不相等的字符差,另一种情况,较长字符串的前面部分恰好是较短的字符串,则返回他们的长度差
public class StringBuilderTest { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("java"); sb.insert(0, "hello "); sb.replace(5, 6, ","); System.out.println(sb); System.out.println(sb.length()); System.out.println(sb.capacity()); sb.setLength(5); System.out.println(sb); } }
// StringBuilder与String之间最大区别:StringBuilder的字符序列是可变的,
Math类
Math类是一个工具类,他的构造器是私有的,Math类的所有方法都是类方法,直接通过类名来调用。还有类变量 PI 和 E。
BigDecimal类
public class BigDecimal { public static void main(String[] args) { //使用字符串 BigDecimal f1 = new BigDecimal("0.05"); // 如果使用double浮点数作为BigDecimal构造器的参数时,不要直接将该double浮点数作为构造器参数,应该通过BigDecimal。valueOf(double value)静态方法来创建对象。 BigDecimal f2 = BigDecimal.valueOf(0.01); BigDecimal f3 = new BigDecimal(0.05); } }
Java8的日期时间类未看
第八章 Java集合
Hashmap和Hashtable的区别
相同点:都是java的集合类,都可以用来存放java对象。
不同点 (1)历史原因:Hashtable是基于陈旧的Dictionary类的,Hashmap是基于Java1.2引进的Map接口的一个实现
(2)同步性:Hashtable是同步的,这个类中的一些方法保证了Hashtable中的对象时线程安全的。而HashMap则是异步的,因此HashMap中的对象并不是线程安全的,因为同步的要求会影响执行的效率,所以如果不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免同步带来不必要的性能开销,从而提高效率。
(3)值:HashMap 可以让你将空值作为一个key或者value,hashTable不能置null;
ArrayList和Vector区别
(1)同步性: vector是同步的,这个类中的一些方法保证了Vector中的对象时线程安全的,而ArrayList则是异步的,因此ArrayList的对象并不是线程安全的。
(2)数据增长: Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,如果存储大量的数据,用Vector有一些优势。
-----------------------------------
1、如果要求线程安全,使用vector,hashtable
2、如果不要求线程安全,应该使用ArrayList, LinkedList, HashMap
3、如果要求键值对,使用HashMap, Hashtable
4、如果数据量很大,又要线程安全,考虑vector
第九章 泛型
作用 (安全,提高代码重用率)
import java.lang.reflect.Method; public class Demo9_1 { public static void main(String[] args) { Gen<Bird> gen = new Gen<Bird>(new Bird()); gen.showTypeName(); } } class Bird { public void test1() { System.out.println("aaa"); } public void count(int a, int b) { System.out.println(a + b); } } //定义一个类 class Gen <T> { private T o; // 构造函数 public Gen(T a) { o = a; } // 得到T的类型名称 public void showTypeName() { System.out.println("类型是:" + o.getClass().getName()); //利用反射机制,可以得到T这个类型的很多信息(比如得到成员函数名) Method[] m = o.getClass().getDeclaredMethods(); // 打印 for (int i = 0; i < m.length; i++) { System.out.println(m[i].getName()); } } }
特点:
1.类型安全 2.向后兼容 3.层次清晰 4.性能较高。
泛型能够通过反射机制,拿到类的信息
第十章 异常处理
两种处理异常的方法:
1.在异常发生的地方处理
2.异常抛给调用者,让调用者处理
异常的种类
1.检查性异常:程序正确,外部环境条件引发
// 检查异常1. 打开文件 FileReader fr = new FileReader("D:\\aaa.txt"); //2.连接一个ip为192.168.1.2端口号为4568 Socket s = new Socket("192.168.1.2", 78);
2、运行期异常:
除以0,数组越界
3、错误。少见,很难通过程序解决。他可能源于程序的bug,但一般来自于
异常处理:
1.try-catch-finally
1 try { 2 Socket s = new Socket("192.8168.1.2", 78); 3 //在出现异常的地方就终止执行代码 4 //然后进入到catch 5 //如果有多个catch,进入匹配异常的那个catch语句 6 FileReader fr = new FileReader("D:\\aaa.txt"); 7 }catch(Exception e) 8 { 9 // 把异常信息排出,有利于排bug 10 e.printStackTrace(); 11 //处理 12 }
finally:
1 FileReader fr = null; 2 try { 3 // 假设D盘存在文件,则文件会被打开为了安全,必须在及时关闭 4 fr = new FileReader("D:\\aaa.txt"); 5 Socket s = new Socket("192.8168.1.2", 78); 6 }catch(Exception e) { 7 e.printStackTrace(); 8 //处理 9 }finally { 10 // finally语句,不管有没有异常都会执行 11 //一般来说,把需要关闭的资源 【文件,连接,内存....】 12 if (fr != null) 13 { 14 try { 15 fr.close(); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 } 20 21 }
try ,catch ,finally 可以缺省catch,其中finaly一般会执行
2.throws
1 class Father 2 { 3 private Son son; 4 public Father() 5 { 6 son = new Son(); 7 } 8 public void test1() 9 { 10 //谁调用谁处理 11 try { 12 son.test2(); 13 }catch (Exception e) { 14 e.printStackTrace(); 15 } 16 } 17 } 18 class Son 19 { 20 public void test2() throws Exception // 抛向调用者 21 { 22 FileReader fr = null; 23 fr = new FileReader("D:\\aaa.txt"); 24 } 25 }
java绘图技术 -- 原理
1 /* 2 * 功能:java绘图原理 3 */ 4 package com.test1; 5 import java.awt.*; 6 import javax.swing.*; 7 8 public class Demo4 extends JFrame { 9 MyPanel mp = null; 10 public static void main(String[] args) { 11 // TODO Auto-generated method stub 12 Demo4 demo4 = new Demo4(); 13 } 14 public Demo4() 15 { 16 mp = new MyPanel(); 17 this.add(mp); 18 19 this.setSize(400, 300); 20 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 21 this.setLocation(100, 100); 22 this.setVisible(true); 23 } 24 } 25 // 定义一个MyPanel (用于绘图和现实绘图的区域) 26 class MyPanel extends JPanel 27 { 28 //覆盖 JPanel 的 paint方法 29 // Graphics是绘图的重要类,可以理解为一只画笔 30 public void paint(Graphics g) { 31 // 调用父类函数完成初始化 32 //这句话,不能少 33 super.paint(g); 34 // 画一个椭圆 35 g.drawOval(10, 10, 10, 30); 36 } 37 }
1.(1)paint(Graphics g)绘制组件外观 (2)repaint()刷新组件外观
2.在以下情况下paint()将会被调用:
(1)窗口最小化,再最大化 (2)窗口的大小发生变化 (3)repaint方法被调用
3. 任何一个类实现了接口,就可以监听。步骤如下
a.实现相应的接口 b接口的方法重写 c在事件源上注册监听 d事件传递是靠事件类的
4.事件源:产生事件的对象
事件:承载事件源状态改变时的信息对象
事件监听接口
线程
1.线程的基本概念
进程
是指运行的应用程序,每个进程都有自己独立的地址空间(内存空间)
线程:a 线程是轻量级的进程 b
2.线程的使用
a继承Thread类,并重写run函数 b实现runnable接口
因为java是单继承的,在某些情况下,一个类可能已经继承了某个父类,这时再用继承Thread类方法来创建线程显然不可能,java设计者们提供另一个方法创建线程,就是通过实现Runnable接口实现
3.一个线程类只能启动一次
4.java线程的同步
java任何类型的对象都有一个标志位,该标志位具有0 1两种状态,其开始状态为1,当某个线程执行了synchronized(Object)语句后,object对象的标志位变为0状态,直到执行完整个synochronized语句中的代码块后,该对象的标志位又回到1状态