发表时间:2022-03-25来源:网络
真实世界,二进制没有符号位。
+[0000 0000 0000 0000 0000 0000 1111 1111] = 255
+[0000 0000 0000 0000 0000 0000 0000 0000] = 0
-[0000 0000 0000 0000 0000 0000 0000 0001] = -1
计算机的世界中,二进制都是补码。第一位是符号位。
最小存储单位为比特(bit),计量基本单位是字节(byte)。1byte=8bit 。
[0000 0000 0000 0000 0000 0000 1111 1111] = 255
[0000 0000 0000 0000 0000 0000 0000 0000] = 0
-1的原码:
[1000 0000 0000 0000 0000 0000 0000 0001]
-1的反码:
[1111 1111 1111 1111 1111 1111 1111 1110]
-1的补码:
[1111 1111 1111 1111 1111 1111 1111 1111]
0的原码: [1000 0000 0000 0000 0000 0000 0000 0000] 和 [0000 0000 0000 0000 0000 0000 0000 0000]
0的补码: [1000 0000 0000 0000 0000 0000 0000 0000] 和 [0000 0000 0000 0000 0000 0000 0000 0000]
0在计算机中占用两个编码?
这样吧,规定其中的[1000 0000 0000 0000 0000 0000 0000 0000] = -2147483648 ;
不仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数。
image.png
public class App {
public static void main(String[] args) {
// 左移 左移后,低位补0
//无符号左移>>2); //1
//位与&
// 0000 0000 0000 0000 0000 0000 0000 0101 5
// & 0000 0000 0000 0000 0000 0000 0000 0011 3
// 0000 0000 0000 0000 0000 0000 0000 0001 1
System.out.println(5&3); //1
//位异或 ^
// 0000 0000 0000 0000 0000 0000 0000 0101 5
// ^ 0000 0000 0000 0000 0000 0000 0000 0011 3
// 0000 0000 0000 0000 0000 0000 0000 0110 6
System.out.println(5^3); // 6
// 位非 ~ 一元操作符 按位取反
// 0000 0000 0000 0000 0000 0000 0000 0101 5
// ~ 1111 1111 1111 1111 1111 1111 1111 1010 -6
// 原理:11111111111111111111111111111111 = -1
System.out.println(~5);// -6
}
}
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
protected详解
People.java
Human.java
package com.xzb.javase.enclosure; public class Human { public void sayHuman(){ People people = new People(); people.say(); } }Client.java
package com.xzb.javase.enclosure2; import com.xzb.javase.enclosure.People; public class Client { public void cloneTest(){ //protected : 同一包内的类和所有子类可见。使用对象:变量、方法。 //虽然People是Object的子类,但是Client作用范围内不能使用People爹的clone方法;只能用自己爹的clone方法。 // 虽然是一个爹。但是!我的地盘听我的。 People people = new People(); // people.clone(); //编译失败 try { clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } public static void main(String[] args) { People people = new People(); //people.say();//编译失败 } }default详解
package com.xzb.javase.enclosure2; import com.xzb.javase.enclosure.People; public class Client extends People{ public static void main(String[] args) { People people = new People(); //people.say();//编译失败 } }
执行结果
在对象的内部使用,可以代表父类对象。
访问父类的属性:super.age 访问父类的方法:super.eat()super的应用:
子类的构造过程中必须调用父类的构造方法。这个过程我们使用super关键字隐式调用。如果自己用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行。
1.子类构造方法没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身其他的构造方法,系统默认调用父类的无参构造方法。Super()。
2.子类构造方法通过super显式调用父类的有参构造方法,执行父类相应构造方法,而不执行父类无参构造方法。
父类的引用可以指向本类的对象,可以指向子类的对象;
本类对象和子类对象,同样都是父类的引用,当我们指向不同的对象时,它们调用的方法也是多态的。
本类对象时,调用的方法为本类方法; 创建子类对象时,调用的方法为子类重写的方法或者继承的方法;抽象类前使用abstract关键字修饰,则该类为抽象类。
抽象类不能被实例化。只有抽象类的非抽象子类可以创建对象。
抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
抽象类中的抽象方法只是声明,不包含方法体。
构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
1.接口特性
接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。2.接口与类的区别
接口不能用于实例化对象。 接口没有构造方法。 接口中所有的方法必须是抽象方法。 接口不能包含成员变量,除了 static 和 final 变量。 接口不是被类继承了,而是要被类实现。 接口支持多继承。3.接口与抽象类区别
DK 1.8 以后,接口里可以有静态方法和方法体了。
有且只有一个抽象方法的接口,成为“函数式接口”。
1.使用Lambda必须具有接口,有且接口中仅有一个抽象方法。 2.使用Lambda必须具有上下文推断,即方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。实例2:
package com.itheima.demo05.Lambda; import java.util.Arrays; /* Lambda表达式有参数有返回值的练习 需求: 使用数组存储多个Person对象 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序 */ public class Demo01Arrays { public static void main(String[] args) { //使用数组存储多个Person对象 Person[] arr = { new Person("柳岩",38), new Person("迪丽热巴",18), new Person("古力娜扎",19) }; //对数组中的Person对象使用Arrays的sort方法通过年龄进行升序(前边-后边)排序 /*Arrays.sort(arr, new Comparator() { @Override public int compare(Person o1, Person o2) { return o1.getAge()-o2.getAge(); } });*/ //使用Lambda表达式,简化匿名内部类 Arrays.sort(arr,(Person o1, Person o2)->{ return o1.getAge()-o2.getAge(); }); //优化省略Lambda Arrays.sort(arr,(o1, o2)->o1.getAge()-o2.getAge()); //遍历数组 for (Person p : arr) { System.out.println(p); } } }实例3:
package com.itheima.demo07.Lambda; import java.util.ArrayList; /* Lambda表达式:是可推导,可以省略 凡是根据上下文推导出来的内容,都可以省略书写 可以省略的内容: 1.(参数列表):括号中参数列表的数据类型,可以省略不写 2.(参数列表):括号中的参数如果只有一个,那么类型和()都可以省略 3.{一些代码}:如果{}中的代码只有一行,无论是否有返回值,都可以省略({},return,分号) 注意:要省略{},return,分号必须一起省略 */ public class Demo01ArrayList { public static void main(String[] args) { //JDK1.7版本之前,创建集合对象必须把前后的泛型都写上 ArrayList list01 = new ArrayList(); //JDK1.7版本之后,=号后边的泛型可以省略,后边的泛型可以根据前边的泛型推导出来 ArrayList list02 = new ArrayList(); } }函数式接口是Lambda的基础,而方法引用是Lambda的孪生兄弟。
来看一个简单的函数式接口以应用Lambda表达式:
public class Demo { private static void printString(String str,Consumer sss) { sss.accept(str); } public static void main(String[] args) { printString("xzb", new Consumer() { @Override public void accept(String s) { System.out.println(s);//整个逻辑已经有实现了。 } }); //lamdba printString("xzb1",(s)-> System.out.println(s)); //方法引用 printString("xzb3",System.out::println); } }双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方 法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
定义一个打印的函数式接口:
@FunctionalInterface public interface Printable { void print(String s); } package com.xzb.javase.lambda; public class DemoMethodReference { public static void printString(Printable p){ p.print("Hello"); } public static void main(String[] args) { // 使用匿名内部类 printString(new Printable() { @Override public void print(String s) { System.out.println(s.toUpperCase()); } }); //使用lamdba printString((s)->{ System.out.println(s.toUpperCase()); }); //使用方法引用 MethodRerObject obj = new MethodRerObject(); printString(obj::printUpperCaseString); } static class MethodRerObject { public void printUpperCaseString(String str){ System.out.println(str.toUpperCase()); } } }将类的各个组成部分封装为其他对象,这就是反射机制。
好处:可以在程序运行过程中,操作这些对象;可以解耦,提高程序的可扩展性。
内省和反射浅谈
反射可以操作各种类的属性,而内省只是通过反射来操作JavaBean的属性;
内省设置属性值肯定会调用seter方法,反射可以不用;
内省一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反射机制来调用这些方法。
image.png
获取Class对象的方式:
Class.forName("全类名"):将字节码文件加载进内存,返回Class对象;多用于配置文件,将类名定义在配置文件中。读取文件,加载类。 类名.class:通过类名的属性class获取;多用于参数的传递。 对象.getClass():getClass()方法在Object类中定义着;多用于对象的获取字节码的方式。同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
Class对象功能
* 获取功能: 1. 获取成员变量们 * Field[] getFields() * Field getField(String name) * Field[] getDeclaredFields() * Field getDeclaredField(String name) 2. 获取构造方法们 * Constructor[] getConstructors() * Constructor getConstructor(类... parameterTypes) * Constructor getDeclaredConstructor(类... parameterTypes) * Constructor[] getDeclaredConstructors() 3. 获取成员方法们: * Method[] getMethods() * Method getMethod(String name, 类... parameterTypes) * Method[] getDeclaredMethods() * Method getDeclaredMethod(String name, 类... parameterTypes) 4. 获取类名 * String getName()Person:
public class Person { private String name; private int age; public String a; protected String b; String c; private String d; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void eat(){ System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..."+food); } }1.获取成员变量
public class ReflectDemo2 { public static void main(String[] args) throws Exception { //0.获取Person的Class对象 Class personClass = Person.class; //1.Field[] getFields()获取所有public修饰的成员变量 Field[] fields = personClass.getFields(); for (Field field : fields) { System.out.println(field); } System.out.println("------------"); //2.Field getField(String name) Field a = personClass.getField("a"); //获取成员变量a 的值 Person p = new Person(); Object value = a.get(p); System.out.println(value); //设置a的值 a.set(p,"张三"); System.out.println(p); System.out.println("==================="); //Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符 Field[] declaredFields = personClass.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println(declaredField); } //Field getDeclaredField(String name) Field d = personClass.getDeclaredField("d"); //忽略访问权限修饰符的安全检查 d.setAccessible(true);//暴力反射 Object value2 = d.get(p); System.out.println(value2); } }2.获取构造方法
public class ReflectDemo3 { public static void main(String[] args) throws Exception { //0.获取Person的Class对象 Class personClass = Person.class; //Constructor getConstructor(类... parameterTypes) Constructor constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); //创建对象 Object person = constructor.newInstance("张三", 23); System.out.println(person); System.out.println("----------"); Constructor constructor1 = personClass.getConstructor(); System.out.println(constructor1); //创建对象 空参构造方法使用Class.newInstance() Object person1 = constructor1.newInstance(); System.out.println(person1); Object o = personClass.newInstance(); System.out.println(o); //constructor1.setAccessible(true); } }3. 获取成员方法
public class ReflectDemo4 { public static void main(String[] args) throws Exception { //0.获取Person的Class对象 Class personClass = Person.class; //获取指定名称的方法 Method eat_method = personClass.getMethod("eat"); Person p = new Person(); //执行方法 eat_method.invoke(p); Method eat_method2 = personClass.getMethod("eat", String.class); //执行方法 eat_method2.invoke(p,"饭"); System.out.println("-----------------"); //获取所有public修饰的方法 Method[] methods = personClass.getMethods(); for (Method method : methods) { System.out.println(method); String name = method.getName(); System.out.println(name); //method.setAccessible(true); } //获取类名 String className = personClass.getName(); System.out.println(className);//cn.itcast.domain.Person } }应用:模拟Spring
User :
Springs :
假设有个配置文件
假设已经读取配置文件:
import com.User; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class Springs { public static void main(String[] args) throws Exception { // IOC 和 DI 只是操作对象属性。 //模拟IOC //1.读取 class="com.User" 反射得到对象 Class clazz = Class.forName("com.User"); Object obj = clazz.newInstance(); System.out.println(obj); //2.1 读取 // 对象属性注入 使用构造方法 模拟DI Constructor con = clazz.getConstructor(int.class); Object objCon = con.newInstance(30); System.out.println(objCon); //2.2 读取 中的值 //无参对象属性注入 使用set方法 模拟DI System.out.println("----------"); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true);//暴力反射 if ("name".equals(field.getName())) { //field.set(obj, "xzb"); 可以直接注入,为了模拟使用set方式 Method m = clazz.getDeclaredMethod("setName", String.class); m.invoke(obj,"xzb"); } if ("nick".equals(field.getName())) { field.set(obj,"abo"); } if ("age".equals(field.getName())) { field.set(obj,20); } } System.out.println(obj); //3.放入容器 Map beans = new HashMap(); beans.put(clazz.getName(),obj); //5.从容器取对象 User bean = (User) beans.get("com.User"); System.out.println(bean); //AOP操作对象的方法 //模拟AOP //CGLIB生成代理对象 final User user = bean; User userProxy = (User) Enhancer.create(clazz,new MethodInterceptor(){ public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if("pay".equals(method.getName())){ System.out.println("BEFORE"); method.invoke(user, args); System.out.println("AFTER"); }else{ method.invoke(user, args); } return null; } }); //代理对象放入容器 beans.put("proxy",userProxy); //6.从容器取对象 User beanProxy = (User)beans.get("proxy"); beanProxy.pay(); beanProxy.myFunction(); System.out.println(beanProxy.getClass()); } }
结果
注解概念:说明程序的,给计算机看的。
定义:注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
注解作用分类:
①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
本质:注解本质上就是一个接口,该接口默认继承Annotation接口,自定义注解本质是一个接口类。它的实现类在jvm运行时会自动帮我们创建它的实现类。
public interface MyAnno extends java.lang.annotation.Annotation {}格式:
元注解 public @interface 注解名称{ 属性列表; }属性:接口中的抽象方法。
属性的返回值类型有下列取值: 基本类型、String、枚举、注解、以上类型的数组。 定义了属性,在使用时需要给属性赋值 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略。元注解:用于描述注解的注解
@Target:描述注解能够作用的位置, ElementType取值: TYPE:可以作用于类上;METHOD:可以作用于方法上; FIELD:可以作用于成员变量上。 @Retention:描述注解被保留的阶段, @Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到。 @Documented:描述注解是否被抽取到api文档中。 @Inherited:描述注解是否被子类继承。定义注解
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Service { String value(); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Resource { }Spring待管理的User:
@Service(value = "user888") public class User { @Resource private String name; public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "name='" + name + '\'' + '}'; } }使用注解
public class SpringAnoCheck { public static void main(String[] args) throws Exception { User user = new User(); Map beans = new HashMap(); // 1.获得字节码文件 Class cls = user.getClass(); // 2.检查User是否有@Service注解,有:放入IOC if(cls.isAnnotationPresent(Service.class)){ Service service = (Service)cls.getAnnotation(Service.class); beans.put(service.value(),user); } //3.检查属性是否有@Resource注解,有初始化 Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true);//暴力反射 if (field.isAnnotationPresent(Resource.class)) { field.set(user, "xzb"); } } //4.从容器取对象 User bean = (User) beans.get("user888"); System.out.println(bean); } }
结果
皓盘云建最新版下载v9.0 安卓版
53.38MB |商务办公
ris云客移动销售系统最新版下载v1.1.25 安卓手机版
42.71M |商务办公
粤语翻译帮app下载v1.1.1 安卓版
60.01MB |生活服务
人生笔记app官方版下载v1.19.4 安卓版
125.88MB |系统工具
萝卜笔记app下载v1.1.6 安卓版
46.29MB |生活服务
贯联商户端app下载v6.1.8 安卓版
12.54MB |商务办公
jotmo笔记app下载v2.30.0 安卓版
50.06MB |系统工具
鑫钜出行共享汽车app下载v1.5.2
44.7M |生活服务