Hands-on Programming Exercises — Ch. 9 & 10
ImmutableStudent class with private fields: id (int), name (String), and gpa (double). Provide getters for all fields, but a setter only for gpa with validation (0.0 to 4.0). The id and name are set only through the constructor and can never be changed. In main, create a student, try to update gpa with valid and invalid values.private int id; private String name; private double gpa;. Constructor: ImmutableStudent(int id, String name, double gpa) { this.id = id; this.name = name; this.gpa = gpa; }. Only provide getters for id and name (no setters!). Setter for gpa: public void setGpa(double gpa) { if (gpa >= 0.0 && gpa <= 4.0) this.gpa = gpa; }.this lets you explicitly access the instance variable. This exercise makes you practice distinguishing between local and instance scope.ScopeTest class with an instance variable x = 10. Add a method demonstrate(int x) that receives a parameter named x (same name!). Inside the method, print: (1) the local parameter x, (2) the instance variable using this.x, (3) create a local variable y and print it. Then call the method from main with argument 50.int x = 10;. Method: public void demonstrate(int x) { System.out.println("Parameter x: " + x); System.out.println("Instance x: " + this.x); int y = 99; System.out.println("Local y: " + y); }. The parameter x shadows the instance variable, so use this.x to access the instance one.Pizza class with: instance fields name (String) and price (double), a static variable orderCount = 0, and a static final constant TAX_RATE = 0.16. The constructor increments orderCount. Add a method getTotalPrice() that returns price + price * TAX_RATE. Add a static method getOrderCount(). Create 3 pizzas in main.String name; double price; static int orderCount = 0; public static final double TAX_RATE = 0.16;. Constructor: Pizza(String name, double price) { this.name = name; this.price = price; orderCount++; }. Method: public double getTotalPrice() { return price + price * TAX_RATE; }. Static: public static int getOrderCount() { return orderCount; }.Circle class with a private field radius, a constructor, getter, and setter. Write two static methods in the test class: doubleValue(int n) that doubles a primitive (won't affect the original), and doubleRadius(Circle c) that doubles a circle's radius (WILL affect the original). Demonstrate both in main.public static void doubleValue(int n) { n = n * 2; } — this only changes the local copy. Object method: public static void doubleRadius(Circle c) { c.setRadius(c.getRadius() * 2); } — this modifies the actual object because c is a reference to the same object.new each one!Student class with fields name (String) and gpa (double). Create an array of 4 students. Loop through the array to: (1) print each student, (2) find the student with the highest GPA, (3) calculate the average GPA.Student(String name, double gpa) { this.name = name; this.gpa = gpa; }. Array: Student[] students = { new Student("Ali", 3.5), new Student("Sara", 3.9), new Student("Omar", 3.2), new Student("Lina", 3.7) };. Print: for (Student s : students) System.out.println(s.name + ": " + s.gpa);. Best: for (Student s : students) if (s.gpa > best.gpa) best = s;. Average: for (Student s : students) sum += s.gpa;.School has an Address that is created when the school is built — that's composition (created inside). A School also has a Principal who was hired from outside — that's aggregation (passed in). This exercise asks you to implement both in one class.Address class with a field city. Create a Principal class with a field name. Create a School class that uses composition for Address (created inside the constructor with new Address(city)) and aggregation for Principal (passed in as a parameter). Add a display() method. Show that the Principal exists independently after the school is gone.Address(String city) { this.city = city; }. Principal: Principal(String name) { this.name = name; }. School constructor: School(String name, String city, Principal principal) { this.name = name; this.address = new Address(city); this.principal = principal; }. Key: new Address(city) = composition (inside), this.principal = principal = aggregation (passed in).length(), contains(), charAt(), equals(), and toUpperCase().length(), (2) contains "A" or "a" using contains(), (3) first character is uppercase using charAt(0) and Character.isUpperCase(). Also demonstrate == vs .equals() with two identical strings created differently.System.out.println("Length OK (>= 8): " + (password.length() >= 8));. Contains: System.out.println("Contains 'a': " + password.contains("a"));. Uppercase: System.out.println("Starts with uppercase: " + Character.isUpperCase(password.charAt(0)));. Comparison: System.out.println("s1 == s2 (literals): " + (s1 == s2)); etc.double, 0.1 + 0.2 = 0.30000000000000004. That error compounds across millions of transactions! BigDecimal gives exact results. This exercise also uses Integer.parseInt() for parsing quantities (wrapper classes).BigDecimal. Parse quantity strings using Integer.parseInt() (wrapper class). Calculate subtotal = price × quantity using multiply(). Apply 16% tax using multiply(). Calculate total using add(). Compare results with double arithmetic. Use String constructor for BigDecimal!BigDecimal subtotal = price.multiply(quantity);. Tax: BigDecimal taxRate = new BigDecimal("0.16"); BigDecimal tax = subtotal.multiply(taxRate);. Total: BigDecimal total = subtotal.add(tax);. Always use the String constructor: new BigDecimal("0.16") not new BigDecimal(0.16)!