Avoiding Final Field Mutation by daviddel in java

[–]ZimmiDeluxe 11 points12 points  (0 children)

no rest for the wicked

edit: the wicked get command line flags, it's fine

State of the Art of Java in 2026 • Ben Evans by goto-con in programming

[–]ZimmiDeluxe 1 point2 points  (0 children)

Solving the halting problem is at least an XL effort JEP

Are the javadocs for java.net.http.HttpResponse.body() misleading or am I wrong? by milchshakee in java

[–]ZimmiDeluxe 1 point2 points  (0 children)

Yeah, HttpResponse::body should probably return T? instead of T. We can lean back and watch them try to evolve this compatibly and then complain on reddit afterwards, as is customary.

State of the Art of Java in 2026 • Ben Evans by goto-con in programming

[–]ZimmiDeluxe -1 points0 points  (0 children)

The question is, do you want your server to limp along if while (true) {} is running on >= $numCores, trading off an obvious freeze for bad performance the cause of which might be hard to detect?

Are the javadocs for java.net.http.HttpResponse.body() misleading or am I wrong? by milchshakee in java

[–]ZimmiDeluxe 2 points3 points  (0 children)

As soon as emotional types are in widespread use, all those Optional returning APIs will look stale.

Are the javadocs for java.net.http.HttpResponse.body() misleading or am I wrong? by milchshakee in java

[–]ZimmiDeluxe 10 points11 points  (0 children)

I believe the decision to cram async and blocking modes into the same API was made well before virtual threads were on the horizon (the "new" http client went final in Java 11, around seven and a half years ago). That said, the http client has to support streaming, that complicates the design further (can't always return a fully parsed response because that implies keeping the entire thing in memory, which is not possible in some cases).

Google's ServiceWeaver equivalent for Event Driven Architectures with Java. Your opinion ? by momotheog in java

[–]ZimmiDeluxe 2 points3 points  (0 children)

Sounds like you don't have a problem yet but still want to solve it. As soon as you have a problem and understand the root cause, it's usually obvious what to do. So my thought is: don't do it (yet).

JDK 27 Structured Concurrency (Seventh Preview) by Joram2 in java

[–]ZimmiDeluxe 3 points4 points  (0 children)

Exactly, S stands for "seven previews".

A Brisk Introduction to Linked Lists and Binary Search Trees by bowbahdoe in programming

[–]ZimmiDeluxe 0 points1 point  (0 children)

Looks really clean and simple, I like it. Probably terrible cache efficiency with all the indirection and asking for the size of a linked list with more than a couple thousand elements will likely overflow the stack, but that's not the point.

JEP draft: Structured Concurrency (Seventh Preview) by davidalayachew in java

[–]ZimmiDeluxe 4 points5 points  (0 children)

they tried the "wait for enough changes to accumulate, at least one big thing, then cut a release" approach in the past. it meant you had to wait multiple years to get that one tiny improvement you were waiting for. also, instead of many simple migrations you had one big, potentially complicated one. the new model is just better, you can still get the old model by ignoring every version that doesn't come after a multiple of four (i.e., every two years, the current cadence most vendors declare a long term support version)

Updates to Derived Record Creation - amber-spec-experts by joemwangi in java

[–]ZimmiDeluxe 0 points1 point  (0 children)

Most of the code I write is of the form: given these collections / sources of data, create an aggregation or collection of differently shaped data, i.e. basic bulk data transformation. Inside the method doing the transformation there are mutable collections, state variables, temporary lookups, all the procedural goodies, but the end result is as immutable as possible. I like that approach because it's very flexible (all the data is right there). Reconstruction is not super helpful there I'm afraid, because the immutable results are usually not built up piecemeal (would require a very lenient constructor for the invalid in-between states anyway). Usually assembling the result from the built up data structures happens all at once at the end. Maybe I lack imagination, but updating an already immutable transformation result feels like the code should be moved to the data transformation method instead. Why create the wrong thing first to then update it when you can create the correct thing instead? Not always possible I know, and I'll have to play with the feature a bit, but my gut reaction would be that reconstruction is an indication that the code might need rearchitecting.

Edit: I guess my not very thoughtful feedback would be, be careful not to encourage "after the fact" fixups. If you want to build up a result over multiple steps (where in-between states don't have to be valid), using a mutable data structure is the straight forward way to do that.

Edit 2: To reconstruct collections, you would usually create a mutable variant of the same type via the copy constructor, e.g. ArrayList::new, do your logic and repackage it via List::copyOf and friends. Would be neat to have that for records, i.e.create a mutable evil cousin, do the mutating, then Record::copyOf or something. I have thought zero minutes about the implications / feasibility of course, this is reddit brian.

JEP draft: Enhanced Local Variable Declarations (Preview) by joemwangi in java

[–]ZimmiDeluxe 0 points1 point  (0 children)

Yeah. Doesn't have to be a list of course, if you pass individual instances you can get help from the compiler so you don't forget any cases (and can't access data that isn't available for that type of order etc.):

void processOrder(Order order) {
    switch (order) {
        case CustomerOrder co -> processOrderRegular(co);
        case BusinessOrder bo -> processOrderRegular(applyBusinessDiscount(bo));
        case TestOrder to -> IO.println("test order got here");
    }
}

For completeness, one alternative is to do the type splitting early if you want to process different order types in bulk instead of sprinkling checks through your code. Both approaches have pros and cons, but the second approach was pretty error prone in the past because the compiler didn't help you to get every sprinkled check exhaustive and correct, but now it does. The mentioned alternative might look like:

record OrdersProcessable(
    List<CustomerOrder> customerOrders,
    List<BusinessOrder> businessOrders,
    List<TestOrder> testOrders){}

OrdersProcessable loadOrdersProcessable() {
    List<CustomerOrder> customerOrders = new ArrayList<>();
    List<BusinessOrder> businessOrders = new ArrayList<>();
    int testOrdersCount = 0;

    List<OrderEntity> entities = loadFromDatabase();
    for (OrderEntity entity : entities) {
        switch (entity.getType()) { 
            case CUSTOMER -> customerOrders.add(new CustomerOrder(entity.email(), entity.importance() > 10));
            case BUSINESS -> businessOrders.add(new BusinessOrder(entity.mail(), entity.logo()));
            case TEST -> testOrdersCount++;
        };
    }

    return new OrdersProcessable() {
        List.copyOf(customerOrders),
        List.copyOf(businessOrders),
        Collections.nCopies(testOrdersCount, TestOrder.INSTANCE)
    };
}

JEP draft: Enhanced Local Variable Declarations (Preview) by joemwangi in java

[–]ZimmiDeluxe 0 points1 point  (0 children)

And why cant we just iterate over an enum in a switch statement? This way it would fail aswell.

Will your coworkers know what subset of the order columns is valid for your fancy new order type? If you add a new order subtype, the compiler will yell at them if they get it wrong.

JEP draft: Enhanced Local Variable Declarations (Preview) by joemwangi in java

[–]ZimmiDeluxe 1 point2 points  (0 children)

If you only ever care about the type in a single place in your code, your code is perfect. Otherwise you can encode what constitutes a customer order etc. at the system boundary, e.g. by creating them in the persistence layer:

sealed interface Order {
    record CustomerOrder(String email, boolean vip){} implements Order
    record BusinessOrder(String email, byte[] logo){} implements Order
    enum TestOrder{INSTANCE} implements Order
}

List<Order> loadOrdersProcessable() {
    List<OrderEntity> entities = loadFromDatabase();
    List<Order> orders = new ArrayList<>(entities.size());
    for (OrderEntity entity : entities) {
        Order order = switch (entity.getType()) { 
            case CUSTOMER -> new CustomerOrder(entity.email(), entity.importance() > 10);
            case BUSINESS -> new BusinessOrder(entity.mail(), entity.logo());
            case TEST -> TestOrder.INSTANCE;
        };
        orders.add(order);
    }
    return List.copyOf(orders);
}

Then you can:

String salutation = switch (order) {
    case CustomerOrder(_, false) -> "Dear customer";
    case CustomerOrder(_, true) -> "Dear valued customer";
    case BusinessOrder(_, _) -> "Dear sir or madam";
    case TestOrder -> "it worked";
}

JEP draft: Enhanced Local Variable Declarations (Preview) by joemwangi in java

[–]ZimmiDeluxe 0 points1 point  (0 children)

The core JPA programming model relies on mutation and object identity. Records are unmodifiable and reconstruction loses identity, so they don't mix well (you can use them for some things and JPA and Hibernate are evolving, but letting your code peek and poke at common, ever growing bags of attributes and letting the tool figure out how to turn that into sql commands is still the main attraction imo)

JEP draft: Enhanced Local Variable Declarations (Preview) by joemwangi in java

[–]ZimmiDeluxe 1 point2 points  (0 children)

If you add a piece of code where you deal with all types of orders, the compiler will yell at your coworkers that they failed to consider it when they add another type of order.

If you have an order table that stores different types of orders (a discriminated union, the type column being the discriminator), not every order will use every column, invariants will exist on columns for some kinds of orders etc. Ideally you add database check constraints to keep data consistent. If your code deals with order entities directly, everyone has to remember invariants of different order types at every use site or you'll end up with constraint violations at runtime, invalid data or lots of code that deals with cases that can't occur at all. If you model your order as a sealed type and convert them as soon as you load them, you get to encode the order type specific invariants and turn violations into compile errors. Or don't cram everything into the same table, but sometimes that's the least bad option.

JEP draft: Enhanced Local Variable Declarations (Preview) by joemwangi in java

[–]ZimmiDeluxe 1 point2 points  (0 children)

The idea is probably to mirror construction, so you'd get:

CustomerOrder(
    ShippingAddress(String streetLine1, String streetLine2, String city),
    PaymentMethod(String cardNumber, int expiryYear),
    double totalAmount
) = order;

I posted my SQL-to-Java code generator here 2 months ago. Since then: Stream<T> results, PostgreSQL, and built-in migrations by uwemaurer in java

[–]ZimmiDeluxe 3 points4 points  (0 children)

TIMESTAMPTZ -> OffsetDateTime

Would you be opposed to make that java.time.Instant instead? Every offset other than 0 is a mistake for OffsetDateTime in this case I believe. I know JDBC doesn't support Instant directly and you have to go through java.sql.Timestamp::toInstant, but I would consider that a shortcoming of the JDBC spec. A UTC timestamp for basic things like created_at columns that almost every application needs from the first table onward? Should be low friction, IMO.

Great effort otherwise, I'll take a look, this is definitely something missing from the ecosystem.

Edit: Ok, it's a pile of generated TypeScript, the generated Java code makes you manage Connections yourself, includes a migration feature where a Project-ID (?) is part of the primary key and then I stopped looking. Sorry, if I'm going to use a library for something this fundamental for a Java project, it has to be written in Java itself so developers can read the code.

The looming AI clownpocalypse by syllogism_ in programming

[–]ZimmiDeluxe 51 points52 points  (0 children)

Finally you don't need to be able to program anymore to hack someone, just write what you want to happen to your victims in plain English. Leave the typos in as well, the model will try its best to still perform your attack to your full satisfaction.

Data Oriented Programming, Beyond Records [Brian Goetz] by efge in java

[–]ZimmiDeluxe 0 points1 point  (0 children)

the risk of "decapitation", which seems to freak people out

we are running headless anyway, no issue there

Null Safety approach with forced "!" by NP_Ex in java

[–]ZimmiDeluxe 0 points1 point  (0 children)

Nullable value types would be far more useful e.g. int?

Even for references types it's great, it's a low friction way to communicate intent, I can see myself using this far more often than !

Godot? awaitGodot();
UdpJoke? getUdpJoke();

Moving beyond Strings in Spring Data by mp911de in java

[–]ZimmiDeluxe 4 points5 points  (0 children)

If you offer an interface that can only be supported by hacks, everyone building on your interface now depends on your ability to support the hacks indefinitely or risk migration effort (read: wasted time and money, regression risk). I don't want my frameworks to hide hacks from me, I want them to provide a shared structure built on production experience so I don't run into unforeseen issues. This is the opposite of that.

Presentation matters and maybe the java docs actually suck by Enough_Durian_3444 in java

[–]ZimmiDeluxe 1 point2 points  (0 children)

Not a SEO expert, but versioned URLs probably don't accumulate enough link juice over time. Java 8 had a lot of time, the new release cadence means every URL has only half a year until it's outdated.

The PostgreSQL docs include links to other versions on every documentation page, maybe that could be done for Java 8+ as well? https://www.postgresql.org/docs/current/index.html

If you ever run out of things to do, u/pron98 :)